write() system call(via rdma_get_cm_event) is not honoring a signal with flag SA_RESTART.

KrishnamRaju ErapaRaju Krishna2 at chelsio.com
Wed May 18 14:12:54 UTC 2016


Hello,


write() system call(via rdma_get_cm_event) is not honoring a signal with flag SA_RESTART, IE  rdma_get_cm_event() is returning -1 when it got interrupted by a signal: SIGARLM, but it should actually restart the system call and wait until it get a rdma event.


Below is my rdma application which does initiate alarm/timer when receives RDMA_CM_EVENT_CONNECT_REQUEST and expects RDMA_CM_EVENT_DISCONNECTED when the timer expires.


As rdma_get_cm_event() calls ucma_get_event() via write system call, this system call may be blocked at wait_event_interruptible() until it gets an event or until it gets a signal interrupt.

In Linux environment my  rdma application is running fine(write system call via rdma_get_cm_event is getting restarted when there is a SIGALRM with SA_RESTART flag, and waits until DISCONNECT event).
But runing same application in FreeBSD is failing to restart the interrupted write system call when interrupted by a signal and returns -ENOBUFS error as below:



# ./newlat
rdma_get_cm_event failed -1
rdma_get_cm_event error: No buffer space available
#


---------------------------------------------part of my rdma application --------------------------
        sa.sa_handler = &sig_handler;
        sa.sa_flags = SA_RESTART;
        sigfillset(&sa.sa_mask);


        sigaction(SIGALRM, &sa, NULL);

        while (!done) {
                ret = rdma_get_cm_event(rch, &event);
                if (ret) {
                        fprintf(stderr, "rdma_get_cm_event failed %d\n", ret);
                        perror("rdma_get_cm_event error");
                        done = 1;
                        break;
                }
                local_event = *event;
                rdma_ack_cm_event(event);
                switch (local_event.event) {
                        case RDMA_CM_EVENT_CONNECT_REQUEST:
                                ret = newconn(local_event.id);
                                if (ret)
                                        done = 1;
                                else {
                                        clients++;
                                        if (clients == total_clients) {
                                                if (run_time)
                                                        alarm(run_time);
                                                buf[0] = 1;
                                        }
                                }
                                break;
                        case RDMA_CM_EVENT_DISCONNECTED:
                                disconn(local_event.id);
                                clients--;
                                if (clients == 0)
                                        done = 1;
                                break;
                        case RDMA_CM_EVENT_ESTABLISHED:
                                break;
                        default:
                                fprintf(stderr, "fatal rdma event %u\n", local_event.event);
                                done = 1;
                                ret = -1;
                                break;
                }
        }
        return ret;
}


void sig_handler(int foo)
{
        buf[0] = 0xff;
}



Thanks,
Krishna.


More information about the freebsd-infiniband mailing list