YEEEEEEEESSSSSS !!! Спасибо, dbush, ты спас мой день. Вы правы, я не знал о проблеме с Raise (). Поскольку sigwait блокировал, а затем разблокировал, я думал, что основной поток правильно принимал сигнал

аюсь сделать программу, котораяприостановит его исполнениепока не прибудет сигнал, Затем, после получения сигнала, я просто хочу, чтобы мой кодпродолжить его выполнение с того места, где оно было, Я не хочу, чтобы он выполнял обработчик функций или что-то еще. Есть ли простой способ сделать это? Я боролся в течение недели или около того, читая здесь и там, и мне не удалось получить полностью работоспособный код.

В частности, я хочу, чтобы основная программасоздать тему который ожидает какого-то определенного события (например, пользователь ввел некоторые данные в стандартный ввод). Тем временем основная программа что-то делает, но в какой-то момент она приостанавливает свое выполнение, пока не получит сигнал.

сигнал может прийти из потока, потому что он обнаружилмероприятие или это может быть связано сТайм-аут потому что я не хочу этого ждать вечно.

Я сделал некоторый код, но он не работает, как ожидалось ...

/*
 * 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?

Как я уже сказал, я изучал тонны вопросов о стекопереработке, онлайн-практических рекомендациях, пытался использовать различные системные вызовы (например, pause, sigsuspend), ... но не мог найти способ решить эту проблему :-(

Если вам интересно, почему я не делаю этот код намного проще, не используя поток, потому что это на самом деле не код, который я реализую, а просто более простой пример, чтобы прояснить мой вопрос. Я на самом деле пытаюсь реализовать API сетевого протокола, похожий на API сокетов для моего собственного протокола.

заранее спасибо

Ответы на вопрос(1)

Ваш ответ на вопрос