![](/img/trans.png)
[英]Wait a signal with timeout , if the signal is received just continue the execution (no action associated to the signal)
[英]Wait for signal, then continue execution
我正在尝试制作一个暂停其执行的程序, 直到信号到达 。 然后,在信号到达后,我只想让我的代码继续执行它的位置 。 我不希望它执行函数处理程序或任何其他。 有一个简单的方法吗? 我已经挣扎了一个星期左右,在这里和那里阅读,并没有设法得到一个完整的操作代码。
特别是,我希望主程序创建一个等待某个特定事件发生的线程 (例如,用户已经向stdin输入了一些数据)。 与此同时,主程序正在做一些事情,但在某些时候它会暂停执行,直到收到信号。
信号可能来自线程,因为它已检测到事件,或者可能是由于超时,因为我不希望它等待。
我已经制作了一些代码,但它没有按预期工作......
/*
* This code SHOULD start a thread that gets messages from stdin.
* If the message is a "quit", the thread exits. Otherwise it raises
* a signal that should be caught by the main program.
* The main program simply waits for the message unless a timer of
* 5.5 seconds expires before receiving the signal from the thread.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <signal.h>
#define BSIZE 100 /* Buffer size */
sigset_t mask;
pthread_t tid;
//struct itimerval timervalue;
int milisec = 5500; /* Timeout: 5,5 seconds */
int end = 0;
char buffer[BSIZE];
//Function prototypes
void init(void);
void * thread_job(void *);
void message_rcvd(void);
void wait_for_message_or_timeout(void);
int start_timer(struct itimerval, int);
int stop_timer(struct itimerval);
void on_signal(int);
// MAIN: Wait for message or timeout
int main(int argc, char ** argv) {
init();
while(!end){
wait_for_message_or_timeout();
if(!end)
printf("Message received [%s]\n", buffer);
}
return 0;
}
// INIT: Initializes the signals that the program will wait for
// and creates a thread that will eventually generate a signal
void init()
{
/* Init the signals I want to wait for with sigwait() */
sigemptyset(&mask);
sigaddset(&mask, SIGUSR1);
sigaddset(&mask, SIGALRM);
sigprocmask(SIG_BLOCK, &mask, NULL);
//signal(SIGUSR1, SIG_IGN);
signal(SIGUSR1, on_signal);
/* Create the thread and put it to work */
pthread_t tid;
pthread_create(&tid, NULL, thread_job, NULL);
}
void on_signal(int signum){
printf("on_signal\n");
}
// THREAD CODE -------------
// THREAD JOB: When the user inputs a message, it passes the message
// to the main thread by invoking message_rcvd()
void * thread_job(){
int end = 0;
while(!end){
printf("Input message:");
if (fgets(buffer, BSIZE, stdin) != NULL)
message_rcvd();
}
}
// MESSAGE RECEIVED: If message is not equal to "quit" raise a signal
void message_rcvd(){
if(strcmp(buffer, "quit") == 0){
exit(0);
}else{
printf("Going to raise SIGUSR1...");
if(raise(SIGUSR1) == 0)
printf("raised!\n");
}
}
// WAIT: Should wait for signal SIGUSR1 for some time
void wait_for_message_or_timeout(){
int sigid;
struct itimerval t;
/* Set a timer to prevent waiting for ever*/
printf("Setting timer...\n");
start_timer(t, milisec);
/* Put the process to wait until signal arrives */
sigwait(&mask, &sigid);
switch(sigid){
case SIGUSR1:
printf("Received SIGUSR1: Message avaible!\n");
break;
case SIGALRM:
printf("Received SIGALRM: Timeout\n");
end = 1;
break;
default:
printf("Unknown signal received\n");
break;
}
printf("Stopping timer...\n");
/* Stop timer */
stop_timer(t);
}
// START TIMER: I don't want the timer to cause the execution
// of a handler function
int start_timer(struct itimerval timervalue, int msec)
//int start_timer(int msec)
{
timervalue.it_interval.tv_sec = msec / 1000;
timervalue.it_interval.tv_usec = (msec % 1000) * 1000;
timervalue.it_value.tv_sec = msec / 1000;
timervalue.it_value.tv_usec = (msec % 1000) * 1000;
if(setitimer(ITIMER_REAL, &timervalue, NULL))
{
printf("\nsetitimer() error\n");
return(-1);
}
return(0);
}
// STOP TIMER:
int stop_timer(struct itimerval timervalue)
//int stop_timer()
{
timervalue.it_interval.tv_sec = 0;
timervalue.it_interval.tv_usec = 0;
timervalue.it_value.tv_sec = 0;
timervalue.it_value.tv_usec = 0;
if(setitimer(ITIMER_REAL, &timervalue, NULL))
{
printf("\nsetitimer() error\n");
return(-1);
}
return(0);
}
这是此代码的典型执行。
./signaltest
Setting timer...
Input message:hello
Going to raise SIGUSR1...raised!
Input message:friend
Going to raise SIGUSR1...raised!
Input message:Received SIGALRM: Timeout
Stopping timer...
如您所见,信号SIGUSR1正在被提升并且sigwait正被解除阻塞。 但是,在信号提出后,代码似乎不会继续。 (请注意,我不需要信号处理程序,但我刚刚添加了用于调试目的。我已使用sigprocmask
阻止其执行)
为什么SIGUSR1解锁sigwait但执行不会从那里继续? 解锁后有没有办法让它继续下去? 这似乎适用于SIGALRM,但为什么不适用于SIGUSR1?
正如我所说,我一直在寻找大量的stackoverflow问题,在线howto's,尝试不同的系统调用(例如,暂停,sigsuspend),...但找不到解决这个问题的方法:-(
如果你想知道为什么我不通过不使用线程来更简单地执行此代码是因为这实际上不是我正在实现的代码,而只是一个更简单的示例来使我的问题更清楚。 我实际上是在尝试实现一个网络协议API,类似于我自己的协议的套接字API。
提前致谢
SIGUSR1
信号不会发送到您认为的位置。
在多线程程序中, raise
函数向当前线程发送信号,在这种情况下是thread_job
线程。 所以主线程永远不会看到信号。
您需要保存主线程的线程ID,然后使用pthread_kill
向该线程发送信号。
添加新的全局:
pthread_t main_tid;
然后在启动新线程之前在init
函数中填充它:
void init()
{
main_tid = pthread_self();
...
然后在message_rcvd
,使用pthread_kill
:
if(pthread_kill(main_tid, SIGUSR1) == 0)
printf("raised!\n");
另外,删除thread_job
中end
的定义,并删除init
中tid
的定义。 这些定义掩盖了同名的全局变量。
样本输出:
Setting timer...
Input message:hello
Going to raise SIGUSR1...raised!
Input message:Received SIGUSR1: Message avaible!
Stopping timer...
Message received [hello
]
Setting timer...
test
Going to raise SIGUSR1...raised!
Input message:Received SIGUSR1: Message avaible!
Stopping timer...
Message received [test
]
Setting timer...
Received SIGALRM: Timeout
Stopping timer...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.