static int wait_on_socket (int sock) { struct pollfd fds[1]; fds[0].fd = sock; fds[0].events = POLLIN | POLLERR | POLLHUP; int n = __poll (fds, 1, 5 * 1000); if (n == -1 && __builtin_expect (errno == EINTR, 0)) { /* Handle the case where the poll() call is interrupted by a signal. We cannot just use TEMP_FAILURE_RETRY since it might lead to infinite loops. */ struct timeval now; (void) __gettimeofday (&now, NULL); long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000; while (1) { long int timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000); n = __poll (fds, 1, timeout); if (n != -1 || errno != EINTR) break; (void) __gettimeofday (&now, NULL); } } return n; }
static int open_socket (void) { int sock = __socket (PF_UNIX, SOCK_STREAM, 0); if (sock < 0) return -1; /* Make socket non-blocking. */ int fl = __fcntl (sock, F_GETFL); if (fl != -1) __fcntl (sock, F_SETFL, fl | O_NONBLOCK); struct sockaddr_un sun; sun.sun_family = AF_UNIX; strcpy (sun.sun_path, _PATH_NSCDSOCKET); if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0 && errno != EINPROGRESS) goto out; struct pollfd fds[1]; fds[0].fd = sock; fds[0].events = POLLOUT | POLLERR | POLLHUP; if (__poll (fds, 1, 5 * 1000) > 0) /* Success. We do not check for success of the connect call here. If it failed, the following operations will fail. */ return sock; out: close_not_cancel_no_status (sock); return -1; }
static void __end() { int ii, ievt, rem_count; int len, type, lock_key; DMANODE *outEvent; int oldnumber; int iwait=0; int blocksLeft=0; /* Disable Triggers */ #ifdef TID_MASTER tidDisableTriggerSource(1); #endif /* Before disconnecting... wait for blocks to be emptied */ blocksLeft=tidBReady(); if(blocksLeft) { printf("... end: Blocks left on the TID (%d)\n",blocksLeft); while(iwait < 100) { if(blocksLeft<=0) break; blocksLeft=tidBReady(); iwait++; } printf("... end: Blocks left on the TID (%d)\n",blocksLeft); } tidStatus(); tidIntDisable(); tidIntDisconnect(); /* Execute User defined end */ rocEnd(); CDODISABLE(TIDPRIMARY,1,0); /* we need to make sure all events taken by the VME are collected from the vmeOUT queue */ rem_count = getOutQueueCount(); if (rem_count > 0) { printf("tidprimary_list End: %d events left on vmeOUT queue (will now de-queue them)\n",rem_count); /* This wont work without a secondary readout list (will crash EB or hang the ROC) */ for(ii=0;ii<rem_count;ii++) { __poll(); } } else { printf("tidprimary_list End: vmeOUT queue Empty\n"); } daLogMsg("INFO","End Executed"); if (__the_event__) WRITE_EVENT_; } /* end end block */
void svc_run (void) { int i; struct pollfd *my_pollfd = NULL; int last_max_pollfd = 0; for (;;) { int max_pollfd = svc_max_pollfd; if (max_pollfd == 0 && svc_pollfd == NULL) break; if (last_max_pollfd != max_pollfd) { struct pollfd *new_pollfd = realloc (my_pollfd, sizeof (struct pollfd) * max_pollfd); if (new_pollfd == NULL) { perror (_("svc_run: - out of memory")); break; } my_pollfd = new_pollfd; last_max_pollfd = max_pollfd; } for (i = 0; i < max_pollfd; ++i) { my_pollfd[i].fd = svc_pollfd[i].fd; my_pollfd[i].events = svc_pollfd[i].events; my_pollfd[i].revents = 0; } switch (i = __poll (my_pollfd, max_pollfd, -1)) { case -1: if (errno == EINTR) continue; perror (_("svc_run: - poll failed")); break; case 0: continue; default: INTUSE(svc_getreq_poll) (my_pollfd, i); continue; } break; } free (my_pollfd); }
/* * Interface between xdr serializer and tcp connection. * Behaves like the system calls, read & write, but keeps some error state * around for the rpc level. */ static int readtcp (char *ctptr, char *buf, int len) { struct ct_data *ct = (struct ct_data *)ctptr; struct pollfd fd; int milliseconds = (ct->ct_wait.tv_sec * 1000) + (ct->ct_wait.tv_usec / 1000); if (len == 0) return 0; fd.fd = ct->ct_sock; fd.events = POLLIN; while (TRUE) { switch (__poll(&fd, 1, milliseconds)) { case 0: ct->ct_error.re_status = RPC_TIMEDOUT; return -1; case -1: if (errno == EINTR) continue; ct->ct_error.re_status = RPC_CANTRECV; ct->ct_error.re_errno = errno; return -1; } break; } switch (len = __read (ct->ct_sock, buf, len)) { case 0: /* premature eof */ ct->ct_error.re_errno = ECONNRESET; ct->ct_error.re_status = RPC_CANTRECV; len = -1; /* it's really an error */ break; case -1: ct->ct_error.re_errno = errno; ct->ct_error.re_status = RPC_CANTRECV; break; } return len; }
int ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask) { int tval = -1; /* poll uses a simple millisecond value. Convert it. */ if (timeout != NULL) { if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 || timeout->tv_nsec >= 1000000000) { __set_errno (EINVAL); return -1; } if (timeout->tv_sec > INT_MAX / 1000 || (timeout->tv_sec == INT_MAX / 1000 && ((timeout->tv_nsec + 999999) / 1000000 > INT_MAX % 1000))) /* We cannot represent the timeout in an int value. Wait forever. */ tval = -1; else tval = (timeout->tv_sec * 1000 + (timeout->tv_nsec + 999999) / 1000000); } /* The setting and restoring of the signal mask and the select call should be an atomic operation. This can't be done without kernel help. */ sigset_t savemask; if (sigmask != NULL) __sigprocmask (SIG_SETMASK, sigmask, &savemask); /* Note the ppoll() is a cancellation point. But since we call poll() which itself is a cancellation point we do not have to do anything here. */ int retval = __poll (fds, nfds, tval); if (sigmask != NULL) __sigprocmask (SIG_SETMASK, &savemask, NULL); return retval; }
/* * reads data from the tcp connection. * any error is fatal and the connection is closed. * (And a read of zero bytes is a half closed stream => error.) */ static int readtcp (char *xprtptr, char *buf, int len) { SVCXPRT *xprt = (SVCXPRT *)xprtptr; int sock = xprt->xp_sock; int milliseconds = 35 * 1000; struct pollfd pollfd; do { pollfd.fd = sock; pollfd.events = POLLIN; switch (__poll (&pollfd, 1, milliseconds)) { case -1: if (errno == EINTR) continue; /*FALLTHROUGH*/ case 0: goto fatal_err; default: if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) || (pollfd.revents & POLLNVAL)) goto fatal_err; break; } } while ((pollfd.revents & POLLIN) == 0); if ((len = __read (sock, buf, len)) > 0) return len; fatal_err: ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; return -1; }
__pthread_manager(void *arg) { pthread_descr self = manager_thread = arg; int reqfd = __pthread_manager_reader; struct pollfd ufd; sigset_t manager_mask; int n; struct pthread_request request; /* If we have special thread_self processing, initialize it. */ #ifdef INIT_THREAD_SELF INIT_THREAD_SELF(self, 1); #endif #if !(USE_TLS && HAVE___THREAD) /* Set the error variable. */ self->p_errnop = &self->p_errno; self->p_h_errnop = &self->p_h_errno; #endif /* Block all signals except __pthread_sig_cancel and SIGTRAP */ sigfillset(&manager_mask); sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */ if (__pthread_threads_debug && __pthread_sig_debug > 0) sigdelset(&manager_mask, __pthread_sig_debug); sigprocmask(SIG_SETMASK, &manager_mask, NULL); /* Raise our priority to match that of main thread */ __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); /* Synchronize debugging of the thread manager */ n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request, sizeof(request))); ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG); ufd.fd = reqfd; ufd.events = POLLIN; /* Enter server loop */ while(1) { n = __poll(&ufd, 1, 2000); /* Check for termination of the main thread */ if (getppid() == 1) { pthread_kill_all_threads(SIGKILL, 0); _exit(0); } /* Check for dead children */ if (terminated_children) { terminated_children = 0; pthread_reap_children(); } /* Read and execute request */ if (n == 1 && (ufd.revents & POLLIN)) { n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request, sizeof(request))); #ifdef DEBUG if (n < 0) { char d[64]; write(STDERR_FILENO, d, snprintf(d, sizeof(d), "*** read err %m\n")); } else if (n != sizeof(request)) { write(STDERR_FILENO, "*** short read in manager\n", 26); } #endif switch(request.req_kind) { case REQ_CREATE: request.req_thread->p_retcode = pthread_handle_create((pthread_t *) &request.req_thread->p_retval, request.req_args.create.attr, request.req_args.create.fn, request.req_args.create.arg, &request.req_args.create.mask, request.req_thread->p_pid, request.req_thread->p_report_events, &request.req_thread->p_eventbuf.eventmask); restart(request.req_thread); break; case REQ_FREE: pthread_handle_free(request.req_args.free.thread_id); break; case REQ_PROCESS_EXIT: pthread_handle_exit(request.req_thread, request.req_args.exit.code); /* NOTREACHED */ break; case REQ_MAIN_THREAD_EXIT: main_thread_exiting = 1; /* Reap children in case all other threads died and the signal handler went off before we set main_thread_exiting to 1, and therefore did not do REQ_KICK. */ pthread_reap_children(); if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { restart(__pthread_main_thread); /* The main thread will now call exit() which will trigger an __on_exit handler, which in turn will send REQ_PROCESS_EXIT to the thread manager. In case you are wondering how the manager terminates from its loop here. */ } break; case REQ_POST: sem_post(request.req_args.post); break; case REQ_DEBUG: /* Make gdb aware of new thread and gdb will restart the new thread when it is ready to handle the new thread. */ if (__pthread_threads_debug && __pthread_sig_debug > 0) raise(__pthread_sig_debug); break; case REQ_KICK: /* This is just a prod to get the manager to reap some threads right away, avoiding a potential delay at shutdown. */ break; case REQ_FOR_EACH_THREAD: pthread_for_each_thread(request.req_args.for_each.arg, request.req_args.for_each.fn); restart(request.req_thread); break; } } } }
int rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, struct rpc_timeval *timeout) { int s; struct pollfd fd; int milliseconds; int res; /* RFC 868 says the time is transmitted as a 32-bit value. */ uint32_t thetime; struct sockaddr_in from; int fromlen; int type; if (timeout == NULL) type = SOCK_STREAM; else type = SOCK_DGRAM; s = __socket (AF_INET, type, 0); if (s < 0) return (-1); addrp->sin_family = AF_INET; addrp->sin_port = htons (IPPORT_TIMESERVER); if (type == SOCK_DGRAM) { res = __sendto (s, (char *) &thetime, sizeof (thetime), 0, (struct sockaddr *) addrp, sizeof (*addrp)); if (res < 0) { do_close (s); return -1; } milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); fd.fd = s; fd.events = POLLIN; do res = __poll (&fd, 1, milliseconds); while (res < 0 && errno == EINTR); if (res <= 0) { if (res == 0) __set_errno (ETIMEDOUT); do_close (s); return (-1); } fromlen = sizeof (from); res = __recvfrom (s, (char *) &thetime, sizeof (thetime), 0, (struct sockaddr *) &from, &fromlen); do_close (s); if (res < 0) return -1; } else { if (__connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0) { do_close (s); return -1; } res = __read (s, (char *) &thetime, sizeof (thetime)); do_close (s); if (res < 0) return (-1); } if (res != sizeof (thetime)) { __set_errno (EIO); return -1; } thetime = ntohl (thetime); timep->tv_sec = thetime - TOFFSET; timep->tv_usec = 0; return 0; }
static enum clnt_stat clntudp_call (/* client handle */ CLIENT *cl, /* procedure number */ u_long proc, /* xdr routine for args */ xdrproc_t xargs, /* pointer to args */ caddr_t argsp, /* xdr routine for results */ xdrproc_t xresults, /* pointer to results */ caddr_t resultsp, /* seconds to wait before giving up */ struct timeval utimeout) { struct cu_data *cu = (struct cu_data *) cl->cl_private; XDR *xdrs; int outlen = 0; int inlen; socklen_t fromlen; struct pollfd fd; int milliseconds = (cu->cu_wait.tv_sec * 1000) + (cu->cu_wait.tv_usec / 1000); struct sockaddr_in from; struct rpc_msg reply_msg; XDR reply_xdrs; struct timeval time_waited; bool_t ok; int nrefreshes = 2; /* number of times to refresh cred */ struct timeval timeout; int anyup; /* any network interface up */ if (cu->cu_total.tv_usec == -1) { timeout = utimeout; /* use supplied timeout */ } else { timeout = cu->cu_total; /* use default timeout */ } time_waited.tv_sec = 0; time_waited.tv_usec = 0; call_again: xdrs = &(cu->cu_outxdrs); if (xargs == NULL) goto get_reply; xdrs->x_op = XDR_ENCODE; XDR_SETPOS (xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer */ (*(uint32_t *) (cu->cu_outbuf))++; if ((!XDR_PUTLONG (xdrs, (long *) &proc)) || (!AUTH_MARSHALL (cl->cl_auth, xdrs)) || (!(*xargs) (xdrs, argsp))) return (cu->cu_error.re_status = RPC_CANTENCODEARGS); outlen = (int) XDR_GETPOS (xdrs); send_again: if (__sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0, (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen) != outlen) { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTSEND); } /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { return (cu->cu_error.re_status = RPC_TIMEDOUT); } get_reply: /* * sub-optimal code appears here because we have * some clock time to spare while the packets are in flight. * (We assume that this is actually only executed once.) */ reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; fd.fd = cu->cu_sock; fd.events = POLLIN; anyup = 0; for (;;) { switch (__poll (&fd, 1, milliseconds)) { case 0: if (anyup == 0) { anyup = is_network_up (cu->cu_sock); if (!anyup) return (cu->cu_error.re_status = RPC_CANTRECV); } time_waited.tv_sec += cu->cu_wait.tv_sec; time_waited.tv_usec += cu->cu_wait.tv_usec; while (time_waited.tv_usec >= 1000000) { time_waited.tv_sec++; time_waited.tv_usec -= 1000000; } if ((time_waited.tv_sec < timeout.tv_sec) || ((time_waited.tv_sec == timeout.tv_sec) && (time_waited.tv_usec < timeout.tv_usec))) goto send_again; return (cu->cu_error.re_status = RPC_TIMEDOUT); /* * buggy in other cases because time_waited is not being * updated. */ case -1: if (errno == EINTR) continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } #ifdef IP_RECVERR if (fd.revents & POLLERR) { struct msghdr msg; struct cmsghdr *cmsg; struct sock_extended_err *e; struct sockaddr_in err_addr; struct iovec iov; char *cbuf = malloc (outlen + 256); int ret; if (cbuf == NULL) { cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } iov.iov_base = cbuf + 256; iov.iov_len = outlen; msg.msg_name = (void *) &err_addr; msg.msg_namelen = sizeof (err_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cbuf; msg.msg_controllen = 256; ret = __recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE); if (ret >= 0 && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0 && (msg.msg_flags & MSG_ERRQUEUE) && ((msg.msg_namelen == 0 && ret >= 12) || (msg.msg_namelen == sizeof (err_addr) && err_addr.sin_family == AF_INET && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr, sizeof (err_addr.sin_addr)) == 0 && err_addr.sin_port == cu->cu_raddr.sin_port))) for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) { free (cbuf); e = (struct sock_extended_err *) CMSG_DATA(cmsg); cu->cu_error.re_errno = e->ee_errno; return (cu->cu_error.re_status = RPC_CANTRECV); } free (cbuf); } #endif do { fromlen = sizeof (struct sockaddr); inlen = __recvfrom (cu->cu_sock, cu->cu_inbuf, (int) cu->cu_recvsz, MSG_DONTWAIT, (struct sockaddr *) &from, &fromlen); } while (inlen < 0 && errno == EINTR); if (inlen < 0) { if (errno == EWOULDBLOCK) continue; cu->cu_error.re_errno = errno; return (cu->cu_error.re_status = RPC_CANTRECV); } if (inlen < 4) continue; /* see if reply transaction id matches sent id. Don't do this if we only wait for a replay */ if (xargs != NULL && memcmp (cu->cu_inbuf, cu->cu_outbuf, sizeof (u_int32_t)) != 0) continue; /* we now assume we have the proper reply */ break; } /* * now decode and validate the response */ xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE); ok = xdr_replymsg (&reply_xdrs, &reply_msg); /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ if (ok) { _seterr_reply (&reply_msg, &(cu->cu_error)); if (cu->cu_error.re_status == RPC_SUCCESS) { if (!AUTH_VALIDATE (cl->cl_auth, &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); } } /* end successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth)) { nrefreshes--; goto call_again; } } /* end of unsuccessful completion */ } /* end of valid reply message */ else { cu->cu_error.re_status = RPC_CANTDECODERES; } return cu->cu_error.re_status; }