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