Espere la señal, luego continúe la ejecución

Estoy tratando de hacer un programa quesuspende su ejecuciónhasta que llegue una señal. Luego, después de que llegue la señal, solo quiero que mi códigocontinuar su ejecución desde donde estaba. No quiero que ejecute un controlador de funciones o lo que sea. ¿Hay una manera simple de hacer esto? He estado luchando durante una semana más o menos, leyendo aquí y allá, y no pude obtener un código completamente operativo.

En particular, quiero que el programa principalcrear un hilo que espera que suceda algún evento en particular (por ejemplo, un usuario ha ingresado algunos datos en stdin). Mientras tanto, el programa principal está haciendo algo, pero en algún momento suspende su ejecución hasta que recibe una señal.

losseñal puede provenir del hilo porque ha detectado elevento o puede ser debido a unse acabó el tiempo porque no quiero que espere para siempre.

He hecho un código pero no funciona como se esperaba ...

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

}

Aquí hay una ejecución típica de este 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 puede ver, la señal SIGUSR1 se está elevando y se está desbloqueando sigwait. Sin embargo, el código parece que no continúa después de que se haya generado la señal. (Tenga en cuenta que no necesito un controlador de señal, pero acabo de agregarlo para fines de depuración. He bloqueado su ejecución consigprocmask)

¿Por qué SIGUSR1 desbloquea sigwait pero la ejecución no continúa desde allí? ¿Hay alguna manera de hacerlo continuar después del desbloqueo? Esto parece funcionar para SIGALRM pero ¿por qué no para SIGUSR1?

Como dije, he estado buscando toneladas de preguntas de stackoverflow, procedimientos en línea, probado con diferentes llamadas al sistema (por ejemplo, pausa, sigsuspend), ... pero no pude encontrar una manera de resolver esto :-(

Si se pregunta por qué no estoy haciendo este código mucho más simple al no usar un hilo es porque este no es el código que estoy implementando, sino un ejemplo más simple para aclarar mi pregunta. Realmente estoy tratando de implementar una API de protocolo de red, similar a la API de sockets para mi propio protocolo.

Gracias por adelantado

Respuestas a la pregunta(1)

Su respuesta a la pregunta