2017-02-02 1 views
-1

Mehrere Threads rufen eine Methode auf und richten einen Timer mit timer_create und timer_settime ein. Ich versuche, die Thread-ID intimer_create für mehrere Threads in C++

sev.sigev_value.sival_ptr = &info;

jedoch passieren, wenn der Handler es mit einer anderen Thread-ID kommt genannt wird (wahrscheinlich die Hauptfunktion des id) und meine Abbruchmethode wird nicht aufgerufen.

 timer_t timerid; 
     struct sigevent sev; 
     struct itimerspec its; 
     long long freq_nanosecs; 
     sigset_t mask; 
     struct sigaction sa; 

     sa.sa_flags = SA_SIGINFO; 
     sa.sa_sigaction = &handler; 
     sigemptyset(&sa.sa_mask); 
     sigaction(SIGUSR1, &sa, NULL); 

     sev.sigev_notify = SIGEV_SIGNAL; 
     sev.sigev_signo = SIGUSR1; 
     sev.sigev_value.sival_ptr = &info; 
     timer_create(CLOCK_REALTIME, &sev, &timerid); 
     /* Start the timer */ 

     its.it_value.tv_sec = 3; 
     its.it_value.tv_nsec = 0; 
     its.it_interval.tv_sec = its.it_value.tv_sec; 
     its.it_interval.tv_nsec = its.it_value.tv_nsec; 

     timer_settime(timerid, 0, &its, NULL); 

nun der Handler ist

 Info *inc; 
     inc = (Info *)si->si_value.sival_ptr; 

     std::thread::id thread_id = std::this_thread::get_id(); 

     if(inc->thread_id != thread_id){ 
       LOG << "This thread is not blocking"; 
     } else { 
       printf("Caught signal %d from timer\n", sig); 

       cancel(...); 
     } 

Mein Problem ist, dass ich nicht richtig einen richtigen Weg, um die Abbrechen-Methode auf einem eindeutigen Wert zu identifizieren, basierend identifizieren zu nennen, die von dem aufrufenden Thread kommt.

Jeder Vorschlag

+1

Wollten Sie vielleicht 'SIGEV_THREAD_ID' (das auf das Signal an einem bestimmten Thread abzielt) und nicht' SIGEV_SIGNAL' (das das Signal an den Prozess sendet) verwenden? – Hasturkun

+0

Wenn das der Code Ihres Signalhandlers ist, dann sind die Funktionen, die Sie dort aufrufen, nicht async-signalsicher, d. H. Das ist undefiniertes Verhalten. –

+0

@MaximEgorushkin Dies ist der Code des Signal Handlers in der Tat. Wie sollte ich es verwenden, um async Signal sicher zu sein? – cateof

Antwort

1

Eine Blockierung connect oder read/recv/recvmsg/recvfrom Rückkehr EINTR, wenn sie durch ein Signal unterbrochen und kein SA_RESTART für dieses Signal verwendet wird. Dies war die Hauptabsicht hinter alarm syscall, wurde jedoch vor dem Multithreading erfunden, so dass es das Signal an den Prozess und nicht an einen bestimmten Thread sendet.

Um von einem blockierenden Socket zu trennen, setzen Sie connect Anruf setzen Sie einen Timer, der ein Signal an den bestimmten Thread sendet mit SIGEV_THREAD_ID. Senden Sie den Signalhandler an SIG_IGN und stellen Sie sicher, dass SA_RESTART für dieses Signal nicht verwendet wird.

+0

Ich kann den Socket nicht manipulieren, mein Code hat dort keinen Zugriff. – cateof

+0

Allerdings habe ich einen Verbindungszeiger, dass, wenn ein Timer abläuft kann ich etwas wie cancel (connection_ptr) anrufen – cateof

+0

@cateof Ich würde versuchen, ein Signal an diesen Thread in 'connect blockiert blockiert und sehen, was passiert. Lauf unter "strace". –