This section applies to the signal-handling version of the Message Passing library. Any AIX function that is interruptible by a signal may not behave as expected because the message passing subsystem uses timer signals to manage message traffic. For example, the user's program does not sleep for the full time but returns quickly with an error code of EINTR. This indicates the sleep was interrupted by a signal. This happens for select system call as well.
The following are some sample programs to replace sleep and select.
The following sample replacement program for sleep guarantees to sleep for the specified interval, even if interrupted.
Sleep Example
#include <errno.h> #include <sys/time.h> int SLEEP(int amount) { struct timestruc_t Requested, Remaining; double famount = amount; int rc; while (famount > 0.0) { Requested.tv_sec = (int) famount; Requested.tv_nsec = (int) ((famount - Requested.tv_sec)*1000000000.); rc = nsleep ( &Requested, &Remaining ); if ((rc == -1) && (errno == EINTR)) { /* Sleep interrupted. Resume it */ famount = Remaining.tv_sec + Remaining.tv_nsec / 1000000000.; continue; } else /* Completed sleep. Set return to zero */ { return (0); } } /* end of while */ /* famount = 0; exit */ return (0); }
The following is a sample replacement program for select. SELECT restores the status of the file descriptor bit masks and handles the remaining time after an interrupt.
Select Example
#include <stdio.h> #include <sys/select.h> #include <sys/types.h> #include <sys/time.h> #include <errno.h> int SELECT(int maxfds, fd_set *reads, fd_set *writes, fd_set *errors, struct timeval *timeout) { struct timestruc_t Timer1, Timer2; struct timeval timetogo; static fd_set readcopy; static fd_set writecopy; static fd_set errcopy; int rc; double worktime; double remaining; /* If we get interrupted, will need to restore select bits */ if (reads) bcopy(reads,&readcopy,sizeof(fd_set)); if (writes) bcopy(writes,&writecopy,sizeof(fd_set)); if (errors) bcopy(errors,&errcopy,sizeof(fd_set)); /* two cases: if timeout specifies a time structure, we need to worry about timeouts. Otherwise, we can ignore it */ if (timeout == NULL) { while (TRUE) { rc = select(maxfds,reads,writes,errors,NULL); if ((rc == -1) && (errno == EINTR)) { /* interrupted */ if (reads) bcopy(&readcopy,reads,sizeof(fd_set)); if (writes) bcopy(&writecopy,writes,sizeof(fd_set)); if (errors) bcopy(&errcopy,errors,sizeof(fd_set)); continue; } else return(rc); } } else { /* timeout is not null */ timetogo.tv_sec = timeout->tv_sec; timetogo.tv_usec = timeout->tv_usec; remaining = timetogo.tv_sec + timetogo.tv_usec/1000000.; /* fprintf(stderr,"remaining time = %f\n",remaining); fflush(stderr); */ gettimer(TIMEOFDAY, &Timer2); while (TRUE) { Timer1.tv_sec = Timer2.tv_sec; Timer1.tv_nsec = Timer2.tv_nsec; rc = select(maxfds,reads,writes,errors,&timetogo); if ((rc == -1) && (errno == EINTR)) { /* interrupted */ gettimer(TIMEOFDAY, &Timer2); /* compute amount remaining */ worktime = (Timer2.tv_sec - Timer1.tv_sec) + (Timer2.tv_nsec - Timer1.tv_nsec)/1000000000.; remaining = remaining - worktime; timetogo.tv_sec = (int) remaining; timetogo.tv_usec = (int) ((remaining - timetogo.tv_sec)* 1000000.); /* restore the select bits */ if (reads) bcopy(&readcopy,reads,sizeof(fd_set)); if (writes) bcopy(&writecopy,writes,sizeof(fd_set)); if (errors) bcopy(&errcopy,errors,sizeof(fd_set)); continue; } else return(rc); } } }