对于在用户态陷入死循环的线程是不是毫无办法了?
linux的多线程编程中遇到问题了,如果我检测到某个线程可能进入了死循环,想对它进行操作,(不是要停止它,因此不能pthread_cancel),发现通过给它发信号的方式不行,因为它只会在从内核态返回用户态的时候才去检查并且处理信号,而现在永远也进不了内核态了,
请教大侠,这种情况怎么办?除了杀掉他,还能有什么办法让他停止执行死循环代码吗? 原帖由 acewind 于 2008-10-21 09:18 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
发现通过给它发信号的方式不行,因为它只会在从内核态返回用户态的时候才去检查并且处理信号,而现在永远也进不了内核态了,
我不相信 Linux 的线程实现真这么弱智
回复 #2 MMMIX 的帖子
虚心请教一下,该怎么办? 按理说,每次时钟中断返回也会检查是否有信号等待处理,但是就是没触发 发现通过给它发信号的方式不行,因为它只会在从内核态返回用户态的时候才去检查并且处理信号,而现在永远也进不了内核态了请问这是何处的理论?
你的想法和前段时间在C++版看到的“如何屏蔽段错误让程序继续运行?”性质相似。线程进入死循环明显是编程逻辑上的错误,即使通过信号跳出(确实可以办到),还不是治标不治本吗? 是这样的,我的程序里面有一个死循环检测的功能,可以通过CPU的占有率检测到某一个线程有可能发生了死循环
然后我想知道这个线程在什么地方发生了死循环
于是我打算通过发信号的方式,发一个信号给这个发生死循环的线程,这样就能在它的上下文执行预先挂好的信号处理函数,在信号处理函数中回溯自己的堆栈,从而打印出函数调用链 原帖由 acewind 于 2008-10-21 10:04 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
虚心请教一下,该怎么办?
发信号。如果这样不行,把你的代码贴上来。 原帖由 acewind 于 2008-10-21 13:04 发表 http://linux.chinaunix.net/bbs/images/common/back.gif
是这样的,我的程序里面有一个死循环检测的功能,可以通过CPU的占有率检测到某一个线程有可能发生了死循环
然后我想知道这个线程在什么地方发生了死循环
于是我打算通过发信号的方式,发一个信号给这个发生 ...
呵呵,大概明白你想做什么了,是不是要实现类似下面的功能呢?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <execinfo.h>
#include <sys/select.h>
void sig_rt(int signo, siginfo_t *info, void *context);
void *trace(void *arg);
int Sleep(int sec);
int main(int argc, char *argv[])
{
pthread_t tid;
assert(pthread_create(&tid, NULL, trace, NULL) == 0);
Sleep(3);
pthread_kill(tid, SIGRTMAX);
fprintf(stdout, "Send signal to thread: 0x%x\n", (unsigned int)tid);
Sleep(9);
return 0;
}
void sig_rt(int signo, siginfo_t *info, void *context)
{
void *array[10];
size_t size;
char **strings;
size_t i;
if (signo == SIGRTMAX) {
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
fprintf (stderr, "Thread(0x%x) obtained %zd stack frames.\n", (unsigned int)pthread_self(), size);
for (i = 0; i < size; i++)
fprintf (stderr, "%s\n", strings[i]);
free (strings);
} else {
fprintf(stderr, "Another signo:%d", signo);
}
}
void *trace(void *arg)
{
sigset_t newset;
struct sigaction act;
sigemptyset(&newset);
sigaddset(&newset, SIGRTMAX);
pthread_sigmask(SIG_BLOCK, &newset, NULL);
act.sa_sigaction = sig_rt;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
sigaction(SIGRTMAX, &act, NULL);
Sleep(6);
pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
sleep(3);
return NULL;
}
int Sleep(int sec)
{
struct timeval sTime;
sTime.tv_sec = sec;
sTime.tv_usec = 0;
return select(0, NULL, NULL, NULL, &sTime);
}
73,0-1 Bot
输出如下:
Send signal to thread: 0xb7fcaba0
Thread(0xb7fcaba0) obtained 5 stack frames.
./trace(sig_rt+0x22)
/lib/tls/libpthread.so.0
./trace(trace+0xb8)
/lib/tls/libpthread.so.0
/lib/tls/libc.so.6(__clone+0x5e)
[ 本帖最后由 timespace 于 2008-10-21 15:45 编辑 ] 不会死循环的,硬件中断保证调度器有机会执行,不然哪来的involuntary context switch
页:
[1]