gpt4 book ai didi

c++ - gettimeofday 异步信号安全吗?如果在信号处理程序中使用它会导致死锁吗?

转载 作者:IT王子 更新时间:2023-10-29 01:15:28 50 4
gpt4 key购买 nike

之前我曾询问过 question 如何终止因 I/O 而阻塞的线程。考虑到一些优点,我使用了 pthread_kill() 而不是 pthread_cancel() 或写入管道。在使用 pthread_kill() 实现将信号 (SIGUSR2) 发送到目标线程的代码后,最初它运行良好并且没有遇到任何问题。

static void signalHandler(int signum) {
LogInfo("SIGNAL HANDLER : %d",signum); //print info message using logger utility
}

void setSignalHandler() {
struct sigaction actions;

memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = signalHandler;

int rc = sigaction(SIGUSR2,&actions,NULL);
if(rc < 0) {
LogError("Error in sigaction"); //print error using logger utility
}
}

void stopThread() {
fStop = 1; //set the flag to stop the thread
if( ftid ) { //ftid is pthread_t variable of thread that needs to be terminated.
LogInfo("Before pthread_kill()");
int kill_result = pthread_kill(ftid,SIGUSR2); // send signal to interrupt the thread if blocked for poll() I/O
LogInfo("pthread_kill() returned : %d ( %s )",kill_result,strerror(kill_result));
int result = pthread_join( ftid, NULL );
LogInfo("Event loop stopped for %s", fStreamName);
LogInfo( "pthread_join() -> %d ( %s )\n", result, strerror(result) );
if( result == 0 ) ftid = 0;
}
}

最近我注意到一个死锁问题,其中很少有线程(试图记录语句)被下面的堆栈跟踪阻塞

#0  0x00007fc1b2dc565c in __lll_lock_wait_private () from /lib64/libc.so.6
#1 0x00007fc1b2d70f0c in _L_lock_2462 () from /lib64/libc.so.6
#2 0x00007fc1b2d70d47 in __tz_convert () from /lib64/libc.so.6
#3 0x00000000004708f7 in Logger::getCurrentTimestamp(char*) ()
当调用 LogInfo()LogError() 函数时,从我们的记录器模块调用

getCurrentTimestamp(char*) 函数。此函数内部调用 gettimeofday() 以在日志中打印当前时间。所以我怀疑在 signalHandler() 内部调用的 LogInfo() 函数(调用 gettimeofday())可能会导致死锁问题。但我对此没有信心,因为这个问题没有经常被重现,而且我没有得到任何信息表明 gettimeofday() 不是异步信号安全的。

gettimeofday() 是 thread safe,我认为它不是异步信号安全的,因为它没有列在 async signal safe functions 下。

1) 我可以认为 gettimeofday() 不是异步信号安全的,它是死锁的根本原因吗?

2) 是否存在使用 pthread_kill() 可能导致死锁的任何已知问题?

编辑:

下面是getCurrentTimeStamp()函数的定义

char* Logger::getCurrentTimestamp ( char *tm_buff ) {
char curr_time[ 32 ] = { 0 };
time_t current = time( NULL );
struct timeval detail_time;

if ( tm_buff ) {
strftime( curr_time, sizeof(curr_time), "%Y-%m-%d-%H:%M:%S", localtime( &current ) );
gettimeofday( &detail_time, NULL );
sprintf( tm_buff, "%s:%03d", curr_time, (int) (detail_time.tv_usec / 1000) );
return (tm_buff);
}
return (NULL);
}

被信号中断的线程的堆栈跟踪。

#0  0x00007fc1b2dc565c in __lll_lock_wait_private () from /lib64/libc.so.6
#1 0x00007fc1b2d70f0c in _L_lock_2462 () from /lib64/libc.so.6
#2 0x00007fc1b2d70d47 in __tz_convert () from /lib64/libc.so.6
#3 0x00000000004708f7 in Logger::getCurrentTimestamp(char*) ()
#4 0x000000000046e80f in Log::write(Logger*, LogType, std::string const&, char const*) ()
#5 0x000000000046df74 in Log::i(Logger*, char const*, std::string const&, std::string const&, char const*, ...) ()
#6 0x0000000000456b67 in ?? ()
#7 <signal handler called>
#8 0x00007fc1b2da8dc5 in _xstat () from /lib64/libc.so.6
#9 0x00007fc1b2d71056 in __tzfile_read () from /lib64/libc.so.6
#10 0x00007fc1b2d703b4 in tzset_internal () from /lib64/libc.so.6
#11 0x00007fc1b2d70d63 in __tz_convert () from /lib64/libc.so.6
#12 0x00000000004708f7 in Logger::getCurrentTimestamp(char*) ()
#13 0x000000000047030e in Logger::writeLog(int, std::string&, std::string&) ()
#14 0x0000000000470633 in Logger::Write(Logger*, int, std::string, std::string const&) ()
#15 0x000000000046eb02 in Log::write(Logger*, LogType, std::string const&, char const*) ()
#16 0x000000000046df74 in Log::i(Logger*, char const*, std::string const&, std::string const&, char const*, ...) ()

最佳答案

gettimeofday 本身不是信号安全的,正如您已经发现的那样。

但是,“POSIX.1-2008 将 gettimeofday() 标记为已过时,建议改用 clock_gettime(2)。”( source ) 和 clock_gettimesignal-safe (并且也是线程安全的),因此这可能是您的替代方案。

关于c++ - gettimeofday 异步信号安全吗?如果在信号处理程序中使用它会导致死锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53155166/

50 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com