int PWrite(int sfd, const char *const buf0, size_t size) { volatile int nleft; const char *volatile buf = buf0; int nwrote; #if !defined(NO_SIGNALS) && defined(SIGPIPE) vsio_sigproc_t sigpipe; if (SSetjmp(gPipeJmp) != 0) { (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); nwrote = size - nleft; if (nwrote > 0) return (nwrote); errno = EPIPE; return (kBrokenPipeErr); } sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler); #endif nleft = (int) size; forever { nwrote = write(sfd, buf, nleft); if (nwrote < 0) { if (errno != EINTR) { nwrote = size - nleft; if (nwrote == 0) nwrote = -1; goto done; } else { errno = 0; nwrote = 0; /* Try again. */ } } nleft -= nwrote; if (nleft <= 0) break; buf += nwrote; } nwrote = size - nleft; done: #if !defined(NO_SIGNALS) && defined(SIGPIPE) (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); #endif return (nwrote); } /* PWrite */
int SSendtoByName(int sfd, const char *const buf, size_t size, int fl, const char *const toAddrStr, int tlen) { int nwrote, tleft, result; vsio_sigproc_t sigalrm, sigpipe; time_t done, now; struct sockaddr_in toAddr; if ((result = AddrStrToAddr(toAddrStr, &toAddr, -1)) < 0) { return (result); } if (SSetjmp(gNetTimeoutJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); errno = ETIMEDOUT; return (kTimeoutErr); } if (SSetjmp(gPipeJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); errno = EPIPE; return (kBrokenPipeErr); } sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler); time(&now); done = now + tlen; tleft = (int) (done - now); forever { (void) alarm((unsigned int) tleft); nwrote = sendto(sfd, buf, size, fl, (struct sockaddr *) &toAddr, (int) sizeof(struct sockaddr_in)); (void) alarm(0); if (nwrote >= 0) break; if (errno != EINTR) break; /* Fatal error. */ errno = 0; time(&now); tleft = (int) (done - now); if (tleft < 1) { nwrote = kTimeoutErr; errno = ETIMEDOUT; break; } } (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); return (nwrote); } /* SSendtoByName */
void (*SSignal(int signum, void (*handler)(int)))(int) { #ifdef HAVE_SIGACTION struct sigaction sa, osa; (void) sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; if (signum == SIGALRM) { #ifdef SA_INTERRUPT sa.sa_flags |= SA_INTERRUPT; #endif } else { #ifdef SA_RESTART sa.sa_flags |= SA_RESTART; #endif } if (sigaction(signum, &sa, &osa) < 0) return (SIG_ERR); return (osa.sa_handler); #else return SSignal(signum, handler); #endif /* HAVE_SIGACTION */ }
int SRecvfrom(int sfd, char *const buf, size_t size, int fl, struct sockaddr_in *const fromAddr, int tlen) { int nread, tleft; vsio_sigproc_t sigalrm, sigpipe; time_t done, now; int alen; if (SSetjmp(gNetTimeoutJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); errno = ETIMEDOUT; return (kTimeoutErr); } if (SSetjmp(gPipeJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); errno = EPIPE; return (kBrokenPipeErr); } sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler); time(&now); done = now + tlen; tleft = (int) (done - now); forever { alen = sizeof(struct sockaddr_in); (void) alarm((unsigned int) tleft); nread = recvfrom(sfd, buf, size, fl, (struct sockaddr *) fromAddr, &alen); (void) alarm(0); if (nread >= 0) break; if (errno != EINTR) break; /* Fatal error. */ errno = 0; time(&now); tleft = (int) (done - now); if (tleft < 1) { nread = kTimeoutErr; errno = ETIMEDOUT; break; } } (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); return (nread); } /* SRecvfrom */
int main() {int i,j=0; i =2; while(j<500) { SWait(5); SWait(i); SWait((i+1)%5); SIncrement(i); //Eat SSignal(i); SSignal((i+1)%5); SSignal(5); //Think j++; } }
int SAcceptA(int sfd, struct sockaddr_in *const addr, int tlen) { int result; #ifndef NO_SIGNALS vsio_sigproc_t sigalrm, sigpipe; #endif size_t size; if (tlen < 0) { errno = 0; for (;;) { size = sizeof(struct sockaddr_in); result = accept(sfd, (struct sockaddr *) addr, (int *) &size); if ((result >= 0) || (errno != EINTR)) return (result); } } #ifndef NO_SIGNALS if (SSetjmp(gNetTimeoutJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); errno = ETIMEDOUT; return (kTimeoutErr); } sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIG_IGN); alarm((unsigned int) tlen); errno = 0; do { size = sizeof(struct sockaddr_in); result = accept(sfd, (struct sockaddr *) addr, (int *) &size); } while ((result < 0) && (errno == EINTR)); alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); return (result); #else return (-1); #endif } /* SAcceptA */
int UAcceptA(int sfd, struct sockaddr_un *const addr, int *ualen, int tlen) { int result; vsio_sigproc_t sigalrm, sigpipe; if (tlen < 0) { errno = 0; for (;;) { *ualen = (int) sizeof(struct sockaddr_un); result = accept(sfd, (struct sockaddr *) addr, (int *) ualen); if ((result >= 0) || (errno != EINTR)) return (result); } } if (SSetjmp(gNetTimeoutJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); errno = ETIMEDOUT; return (kTimeoutErr); } sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIG_IGN); alarm((unsigned int) tlen); errno = 0; do { *ualen = (int) sizeof(struct sockaddr_un); result = accept(sfd, (struct sockaddr *) addr, (int *) ualen); } while ((result < 0) && (errno == EINTR)); alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); return (result); } /* UAcceptA */
int SWrite(int sfd, const char *const buf0, size_t size, int tlen, int swopts) { volatile int nleft; const char *volatile buf = buf0; int nwrote, tleft; vsio_sigproc_t sigalrm, sigpipe; time_t done, now; if (SSetjmp(gNetTimeoutJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); nwrote = size - nleft; if (nwrote > 0) return (nwrote); errno = ETIMEDOUT; return (kTimeoutErr); } if (SSetjmp(gPipeJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); nwrote = size - nleft; if (nwrote > 0) return (nwrote); errno = EPIPE; return (kBrokenPipeErr); } sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler); nleft = (int) size; time(&now); done = now + tlen; forever { tleft = (int) (done - now); if (tleft < 1) { nwrote = size - nleft; if (nwrote == 0) { nwrote = kTimeoutErr; errno = ETIMEDOUT; } goto done; } (void) alarm((unsigned int) tleft); nwrote = write(sfd, buf, nleft); (void) alarm(0); if (nwrote < 0) { if (errno != EINTR) { nwrote = size - nleft; if (nwrote == 0) nwrote = -1; goto done; } else { errno = 0; nwrote = 0; /* Try again. */ } } nleft -= nwrote; if (nleft <= 0) break; buf += nwrote; time(&now); } nwrote = size - nleft; done: (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); return (nwrote); } /* SWrite */
int SRecv(int sfd, char *const buf0, size_t size, int fl, int tlen, int retry) { int nread; volatile int nleft; char *volatile buf = buf0; int tleft; vsio_sigproc_t sigalrm, sigpipe; time_t done, now; if (SSetjmp(gNetTimeoutJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); nread = size - nleft; if ((nread > 0) && (retry == kFullBufferNotRequired)) return (nread); errno = ETIMEDOUT; return (kTimeoutErr); } if (SSetjmp(gPipeJmp) != 0) { alarm(0); (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); nread = size - nleft; if ((nread > 0) && (retry == kFullBufferNotRequired)) return (nread); errno = EPIPE; return (kBrokenPipeErr); } sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler); errno = 0; nleft = (int) size; time(&now); done = now + tlen; forever { tleft = (int) (done - now); if (tleft < 1) { nread = size - nleft; if ((nread == 0) || (retry == kFullBufferRequired)) { nread = kTimeoutErr; errno = ETIMEDOUT; } goto done; } (void) alarm((unsigned int) tleft); nread = recv(sfd, (char *) buf, nleft, fl); (void) alarm(0); if (nread <= 0) { if (nread == 0) { /* EOF */ if (retry == kFullBufferRequiredExceptLast) nread = size - nleft; goto done; } else if (errno != EINTR) { nread = size - nleft; if (nread == 0) nread = -1; goto done; } else { errno = 0; nread = 0; /* Try again. */ } } nleft -= nread; if ((nleft <= 0) || ((retry == 0) && (nleft != (int) size))) break; buf += nread; time(&now); } nread = size - nleft; done: (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); return (nread); } /* SRecv */
int SClose(int sfd, int tlen) { #ifdef UNIX_SIGNALS volatile sio_sigproc_t sigalrm = (sio_sigproc_t) 0; volatile sio_sigproc_t sigpipe = (sio_sigproc_t) 0; volatile alarm_time_t oalarm = 0; int result; int oerrno; if (sfd < 0) { errno = EBADF; return (-1); } if (GetSocketLinger(sfd, NULL) <= 0) { /* Linger wasn't on, so close shouldn't block. * Take the regular way out. */ return (SCloseSocket(sfd)); } if (tlen < 1) { /* Don't time it, shut it down now. */ if (SetSocketLinger(sfd, 0, 0) == 0) { /* Linger disabled, so close() * should not block. */ return (SCloseSocket(sfd)); } else { /* This may result in a fd leak, * but it's either that or hang forever. */ (void) shutdown(sfd, 2); return (SCloseSocket(sfd)); } } if (SSetjmp(gNetTimeoutJmp) != 0) { (void) alarm(0); (void) SetSocketLinger(sfd, 0, 0); errno = 0; (void) shutdown(sfd, 2); result = closesocket(sfd); oerrno = errno; (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); (void) alarm(oalarm); errno = oerrno; return (result); } sigalrm = (sio_sigproc_t) SSignal(SIGALRM, SIOHandler); sigpipe = (sio_sigproc_t) SSignal(SIGPIPE, SIG_IGN); oalarm = alarm((alarm_time_t) tlen); for (errno = 0;;) { result = closesocket(sfd); if (result == 0) break; if (errno != EINTR) break; } oerrno = errno; (void) alarm(0); if ((result != 0) && (errno != EBADF)) { (void) SetSocketLinger(sfd, 0, 0); (void) shutdown(sfd, 2); result = closesocket(sfd); oerrno = errno; } (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm); (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe); (void) alarm(oalarm); errno = oerrno; return (result); #else /* ! UNIX_SIGNALS */ if (sfd < 0) { errno = EBADF; return (-1); } /* Sorry... it's up to you to make sure you don't block forever * on closesocket() since this platform doesn't have alarm(). * Even so, it shouldn't be a problem unless you use linger mode * on the socket, and nobody does that these days. */ return (SCloseSocket(sfd)); #endif } /* SClose */