作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的程序中有以下代码。
Thread* t = arg->thread;
//at this point, the new thread is being executed.
t->myId = TGetId();
void* (*functor)(void*) = t->functor;
void* fArg = arg->arg;
nfree(arg);
_INFO_PRINTF(1, "Launching thread with ID: %d", t->myId);
sigset_t mask;
sigfillset(&mask); //fill mask with all signals
sigdelset(&mask, SIGUSR1); // allow SIGUSR1 to get to the thread.
sigdelset(&mask, SIGUSR2); // allow SIGUSR2 to get to the thread.
pthread_sigmask(SIG_SETMASK, &mask, NULL); //block some sigs
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = TSignalHandler;
act.sa_mask = mask;
if(sigaction(SIGUSR1, &act, NULL))
{
_ERROR_PRINT(1, "Could not set signal action.");
return NULL;
}
if(sigaction(SIGUSR2, &act, NULL))
{
_ERROR_PRINT(1, "Could not set signal action.");
return NULL;
}
void* ret = functor(fArg);
t->hasReturned = true;
return ret;
执行此代码的线程将在 native linux 上正确调用信号处理程序。问题是,在适用于 Linux 的 Windows 子系统上,程序挂起并带有 SIGUSR1 或 SIGUSR2 是通过 pthread_kill 发送的,它向线程发送信号。为什么这适用于 native ubuntu(通过 VMWARE WORKSTATION 14)和 debian 和 fedora,但不适用于 WSL?
最佳答案
如果在调试器中运行时出现无法重现的挂起错误,则可以在重现挂起后将调试器附加到正在运行的进程。这不会让您在导致挂起时观察到变量的变化,但至少您可以获得挂起发生的确切位置的堆栈跟踪。
一旦知道挂起进程的进程 ID(假设它是 12345),您可以使用:
$ gdb -p 12345
或者,您可以使用会导致生成核心的信号终止进程。我喜欢使用 SIGTRAP
,因为它很容易与 SIGSEGV
区分开来。
$ kill -SIGTRAP 12345
然后您可以使用 gdb
来发现进程卡在什么地方。
附加到正在运行的进程的好处是进程仍然存在。这允许您从调试器调用函数,这样可以更轻松地访问程序中内置的诊断信息。核心文件保留错误,如果挂起的错误难以重现,这将是有益的。
关于c++ - 为什么程序会在 WSL 中挂起?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54791361/
我是一名优秀的程序员,十分优秀!