Skip to content

Commit

Permalink
[core] make the per-process IPC sending non-blocking
Browse files Browse the repository at this point in the history
A process may get stuck (history showed us such real cases) and we do not want to have other processes getting blocked by trying to do an IPC to such procs (if they are stuck, they will not consume their IPC cmds, so the IPC sender will also block after some time, when the pipe's buffer is full).
So, better make the write pipe non-blocking, discard the current IPC cmd and avoid escalating the blocking over other procs.
  • Loading branch information
bogdan-iancu committed Nov 5, 2021
1 parent bd599dc commit 62af720
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions ipc.c
Expand Up @@ -98,7 +98,7 @@ int init_ipc(void)

int create_ipc_pipes( int proc_no )
{
int i;
int optval, i;

for( i=0 ; i<proc_no ; i++ ) {
if (pipe(pt[i].ipc_pipe_holder)<0) {
Expand All @@ -107,11 +107,39 @@ int create_ipc_pipes( int proc_no )
return -1;
}

/* make writing fd non-blocking */
optval = fcntl( pt[i].ipc_pipe_holder[1], F_GETFL);
if (optval == -1) {
LM_ERR("fcntl failed: (%d) %s\n", errno, strerror(errno));
return -1;
}

if (fcntl(pt[i].ipc_pipe_holder[1], F_SETFL, optval|O_NONBLOCK) == -1){
LM_ERR("set non-blocking write failed: (%d) %s\n",
errno, strerror(errno));
return -1;
}


if (pipe(pt[i].ipc_sync_pipe_holder)<0) {
LM_ERR("failed to create IPC sync pipe for process %d, err %d/%s\n",
i, errno, strerror(errno));
LM_ERR("failed to create IPC sync pipe for process %d, "
"err %d/%s\n", i, errno, strerror(errno));
return -1;
}

/* make writing fd non-blocking */
optval = fcntl( pt[i].ipc_sync_pipe_holder[1], F_GETFL);
if (optval == -1) {
LM_ERR("fcntl failed: (%d) %s\n", errno, strerror(errno));
return -1;
}

if (fcntl(pt[i].ipc_sync_pipe_holder[1], F_SETFL, optval|O_NONBLOCK) == -1){
LM_ERR("set non-blocking write failed: (%d) %s\n",
errno, strerror(errno));
return -1;
}

}
return 0;
}
Expand Down Expand Up @@ -167,7 +195,11 @@ static inline int __ipc_send_job(int fd, ipc_handler_type type,
job.payload2 = payload2;

again:
// TODO - should we do this non blocking and discard if we block ??
/* The per-proc IPC write fds are sent to non-blocking (to be sure we
* do not escalate into a global blocking if a single process got stuck.
* In such care the EAGAIN or EWOULDBLOCK will be thrown and we will
* handle as generic error, nothing special to do.
*/
n = write(fd, &job, sizeof(job) );
if (n<0) {
if (errno==EINTR)
Expand Down

0 comments on commit 62af720

Please sign in to comment.