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;
}