Не могу разбудить поток POSIX, используя сигнал - PullRequest
0 голосов
/ 10 мая 2018

Я пишу многопоточную программу для цели Linux, где один поток должен запускаться только при поступлении сигнала SIGIO из UART. Я проверил код без потоков и только обработчик сигнала, который работает нормально, но когда я делаю это поток, что-то идет не так.

Основное создает два потока: GNSSThread и TestThread. TestThread - это просто время (1), которое печатает предложение раз в секунду.

Я пытался играть с другими сигналами, и я могу успешно заставить код исходить из sigwaitinfo () с помощью ввода с клавиатуры ^ C. Я думаю, что это может быть в том, как дескриптор файла UART настроен?

Надеюсь, кто-нибудь может помочь.

Код ниже.

main.c

int main(int argc, char **argv) {
    cout << endl << "Process "<< argv[0] << " started with PID: " << getpid() << endl << endl;

    InitConfig();

    InitThreads();

    return 0;
}

ThreadFn.cpp

sigset_t SigSet;

void InitThreads() {
    pthread_t GNSSThreadID, TestThreadID;

    //Configuring serial port to send SIGIO signal when I/O data ready to this process
    fcntl(Config.GNSSDataLinkLayer->GetFD(), F_SETSIG, SIGIO);
    fcntl(Config.GNSSDataLinkLayer->GetFD(), F_SETFL, O_ASYNC);
    fcntl(Config.GNSSDataLinkLayer->GetFD(), F_SETOWN, getpid());

    //Config thread to receive SIGIO
    sigemptyset(&SigSet);
    sigaddset(&SigSet, SIGIO);
    sigprocmask(SIG_UNBLOCK, &SigSet, NULL);

    pthread_create(&GNSSThreadID, NULL, GNSSThreadFn, NULL);
    pthread_create(&TestThreadID, NULL, TestThreadFn, NULL);

    pthread_join(TestThreadID, NULL);
}

void *GNSSThreadFn(void *param) {
    cout << "Configuring GNSS Thread" << endl;
    siginfo_t SigInfo;
    mutex mtx;

    cout << "Entering GNSS Thread while loop" << endl;

    while(1){
        //Thread suspended until signal arrives
        cout << "Before sigwait" << endl;
        sigwaitinfo(&WaitSet, &SigInfo);
        cout << "After sigwait" << endl;

        //checking for correct file descriptor and if signal caused by send or receive
        if(SigInfo.si_fd == Config.GNSSDataLinkLayer->GetFD() && SigInfo.si_code == POLL_IN){
            cout << "GNSSThreadMaster::ThreadLoop: Serial port read" << endl;
            //Locking mutex while reading talker
            mtx.lock();
            Config.NMEATransportLayer->ReadTalker();
            mtx.unlock();
        }else if(SigInfo.si_fd == Config.GNSSDataLinkLayer->GetFD() && SigInfo.si_code == POLL_OUT){
            tcdrain(Config.GNSSDataLinkLayer->GetFD());
            //Magic sleep to make it work
            usleep(20000);
        }else
            cout << "ThreadLoop: Signal error" << endl;
    }

    return NULL;
}
...