Power

 View Only

System signals cause some functions(select/nanosleep) to fail

  • 1.  System signals cause some functions(select/nanosleep) to fail

    Posted Wed January 18, 2023 09:53 AM
    Edited by dou fu Wed January 18, 2023 10:05 AM
    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;
    }
    ​