Aguarde o sinal e continue a execução

Eu estou tentando fazer um programa quesuspende sua execuçãoaté que um sinal chegue. Depois que o sinal chegar, só quero que meu códigocontinue sua execução de onde estava. Eu não quero que ele execute um manipulador de função ou qualquer outra coisa. Existe uma maneira simples de fazer isso? Estou lutando há mais ou menos uma semana, lendo aqui e ali, e não consegui obter um código totalmente operacional.

Em particular, quero que o programa principalcriar um tópico que aguarda a ocorrência de algum evento específico (por exemplo, um usuário inseriu alguns dados no stdin). Enquanto isso, o programa principal está fazendo algo, mas em algum momento suspende sua execução até receber um sinal.

osinal pode vir do encadeamento porque detectou oevento ou pode ser devido a umtempo esgotado porque não quero que espere para sempre.

Eu fiz um código, mas ele não funciona conforme o esperado ...

/*
 * 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);

}

Aqui está uma execução típica desse código.

./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...

Como você pode ver, o sinal SIGUSR1 está sendo gerado e o sigwait está sendo desbloqueado. No entanto, o código parece não continuar após o sinal ter sido gerado. (Observe que não preciso de um manipulador de sinal, mas acabei de adicionar para fins de depuração. Bloquei sua execução comsigprocmask)

Por que o SIGUSR1 está desbloqueando o sigwait, mas a execução não continua a partir daí? Existe uma maneira de fazê-lo continuar após o desbloqueio? Isso parece funcionar para o SIGALRM, mas por que não para o SIGUSR1?

Como eu disse, estive pesquisando toneladas de perguntas sobre fluxo de pilha, instruções online, tentei com diferentes chamadas do sistema (por exemplo, pausa, sigsuspend), ... mas não consegui encontrar uma maneira de resolver isso :-(

Se você está se perguntando por que não estou fazendo esse código muito mais simples por não usar um thread, é porque esse não é o código que estou implementando, mas apenas um exemplo mais simples para tornar minha pergunta mais clara. Na verdade, estou tentando implementar uma API de protocolo de rede, semelhante à API de soquetes do meu próprio protocolo.

desde já, obrigado

questionAnswers(1)

yourAnswerToTheQuestion