1. If
, which is not what I expect.
(assume that each thread is in select() blocking) in my process will be interrupted too. This is also not what I expect, my goal is that
interrupts.
Original Message:
Sent: Thu January 19, 2023 02:15 PM
From: Dave Marquardt
Subject: System signals cause some functions(select/nanosleep) to fail
Old school UNIX C code to do this would be to callsignal(SIGUSR2, SIG_IGN)
to ignore the SIGUSR2
signal, but these days you'd use sigaction()
instead. If you want to use your own signal handler, pass its address instead of SIG_IGN
.
------------------------------
Dave Marquardt
Sr. Software Engineer
IBM
Austin TX
Original Message:
Sent: Thu January 19, 2023 08:07 AM
From: dou fu
Subject: System signals cause some functions(select/nanosleep) to fail
Thank you for your reply, I will add judgment on EINTR
within my code.
I originally thought that if there was a way to prevent my own signals (such as SIGUSR2
, which actually have nothing to do with these functions) from being passed to these functions, but only be handled by the methods registered in the main
function, it seems that there is no.
------------------------------
dou fu
Original Message:
Sent: Thu January 19, 2023 05:10 AM
From: José Pina Coelho
Subject: System signals cause some functions(select/nanosleep) to fail
Those functions are supposed to exit on signals, returning -1 and setting errno==EINTR.
nanosleep()
At least for nanosleep, the correct way to handle this is to loop while rc==-1 andf errno==EINTR, using the second argument (it gets updated with the remaining time).
ex:
struct timespec standard, arg, remain;
// Initialize standard to your desired value
standard = whatever;
arg=standard;
while(nanosleep(&arg, &remain) == -1 && errno==EINTR) {
// We were interrupted by a signal (you may want to check a global variable to see if you want to actually break the loop)
arg=remain; // Load the remaining time as the next nanosleep argument.
}
If you never need to know the difference between the requested time and remaining time, you can just do this:
arg=standard;
while(nanosleep(&arg, &arg) == -1 && errno==EINTR) { // On interrupt, arg gets updated with the remaining time.
// We were interrupted by a signal (you may want to check a global variable to see if you want to actually break the loop)
}
If you have no use for the "standard" timespec, you can assign arg directly.
Alternatively: have you tried setting SIG_IGN (ignore) or using sighld()/sigignore() ?
select()
From the select() manpage: EINTR - A signal was caught during the select subroutine and the signal handler was installed with an indication that subroutines are not to be restarted
If timing isn't critical, just loop while rc==-1 and errno=EINTR.
If timing is critical, get the nanotime before starting the loop, loop while (rc==-1 and errno=EINTR), then inside the loop look at the difference between the current nanotime and the beforenanotime to decide if you've gone over the nanotime budget.
sleep()
sleep is implemented with nsleep(), use the same trick as the select().
------------------------------
José Pina Coelho
IT Specialist at Kyndryl
Original Message:
Sent: Wed January 18, 2023 07:37 PM
From: dou fu
Subject: System signals cause some functions(select/nanosleep) to fail
Hello, I want to encapsulate a function, such as select()
,nanosleep()
,sleep()
, to achieve a general delay function.
But on my AIX platform, the system signals will cause these functions to fail.
I have tested with other systems and found that the signals sent to the process do not cause these functions used in the same process to end prematurely.
On AIX, I've found that signals seem to be caught and handled twice, first by my signal_handler()
, and second by these functions ending early with errno=EINTR
set. Is there a way to prevent these functions from getting these signals, thanks.
oslevel -s
7200-04-04-2114
Demo code:
// File: ibm.cpp//// Build: g++ -std=c++11 -w -g -maix64 -o delay ibm.cpp//// Start with ./delay//// Send a signal SIGUSR2 to the process with command:// ps aux | grep delay | grep -v grep | awk '{print $2}' | xargs kill -USR2// then the select() nor nanosleep() will be interrupted.#include <stdio.h>#include <unistd.h>#include <signal.h>#include <string.h>#include <errno.h>#include <sys/time.h>#include <sys/select.h>#include <sys/types.h>#include <pthread.h>//delay for n microseconds, 1000000=1s//using nanosleep()void delay_using_nanosleep(int n, const char* p=""){ int n0 = n; int ret = 0; time_t t0; ::time(&t0); struct timespec req; req.tv_sec = n / 1000000; req.tv_nsec = n % 1000000 * 1000; while(1) { //req.tv_sec = n / 1000000; //req.tv_nsec = n % 1000000 * 1000; ret = nanosleep(&req, &req); if(ret != 0) { int no = errno; printf("\ndelay_t()-nanosleep() thread:%s @@@@@@@@@@@@\n", p); printf("nanosleep return %d, errno=%d, left:%d-%d\n\n\n", ret, no, req.tv_sec, req.tv_nsec); if(no == EINTR) continue; } break; } time_t t1; ::time(&t1); if(t1 - t0 < n0 / 1000000) printf("delay()-nanosleep() failed, t1-t0=%d\n", t1-t0);}//delay for n microseconds, 1000000=1s//using select()void delay_using_select(int n, const char* p=""){#if defined (WIN32) Sleep(n / 1000);#else struct timeval tt; int ret; int n0 = n; time_t t0; ::time(&t0); tt.tv_sec = n / 1000000; tt.tv_usec = n % 1000000; while(1) { //tt.tv_sec = n / 1000000; //tt.tv_usec = n % 1000000; ret=select(0, 0, 0, 0, &tt); if(ret<0){ int no = errno; printf("\ndelay_t()-select() thread:%s @@@@@@@@\n", p); printf("select return %d, errno=%d, left:%d-%d\n\n\n", ret, no, tt.tv_sec, tt.tv_usec); if(no == EINTR) { //n = n / 2; //if(n >= 50000) continue; } } break; } time_t t1; ::time(&t1); if(t1 - t0 < n0 / 1000000) printf("delay()-select() failed, t1-t0=%d\n", t1-t0);#endif}void signal_handler(int sig){ if(sig == SIGUSR2) { write(1, "SIGUSR2\n", 8); //signal_count++; }}int main(int argc, char const* argv[]){ int ret = 0; sigset(SIGUSR2, signal_handler); while(1) { printf("main loop...\n"); delay_using_select(3000000, ""); // ---SIGUSR2 will interrupt select() //delay_using_nanosleep(3000000, ""); // --SIGUSR2 will interrupt sleep() } return 0;}
------------------------------
dou fu
------------------------------