Changeset 988 for vendor/current/lib/util/select.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/lib/util/select.c
r740 r988 24 24 #include "lib/util/select.h" 25 25 26 /* This is here because it allows us to avoid a nasty race in signal handling.27 We need to guarantee that when we get a signal we get out of a select immediately28 but doing that involves a race condition. We can avoid the race by getting the29 signal handler to write to a pipe that is in the select/poll list30 31 This means all Samba signal handlers should call sys_select_signal().32 */33 34 static pid_t initialised;35 static int select_pipe[2];36 static volatile unsigned pipe_written, pipe_read;37 38 /*******************************************************************39 Call this from all Samba signal handlers if you want to avoid a40 nasty signal race condition.41 ********************************************************************/42 43 void sys_select_signal(char c)44 {45 int saved_errno = errno;46 47 if (!initialised) return;48 49 if (pipe_written > pipe_read+256) return;50 51 if (write(select_pipe[1], &c, 1) == 1) pipe_written++;52 53 errno = saved_errno;54 }55 56 /*57 * sys_poll expects pollfd's to be a talloc'ed array.58 *59 * It expects the talloc_array_length(fds) >= num_fds+1 to give space60 * to the signal pipe.61 */62 63 int sys_poll(struct pollfd *fds, int num_fds, int timeout)64 {65 int ret;66 67 if (talloc_array_length(fds) < num_fds+1) {68 errno = ENOSPC;69 return -1;70 }71 72 if (initialised != sys_getpid()) {73 if (pipe(select_pipe) == -1)74 {75 int saved_errno = errno;76 DEBUG(0, ("sys_poll: pipe failed (%s)\n",77 strerror(errno)));78 errno = saved_errno;79 return -1;80 }81 82 /*83 * These next two lines seem to fix a bug with the Linux84 * 2.0.x kernel (and probably other UNIXes as well) where85 * the one byte read below can block even though the86 * select returned that there is data in the pipe and87 * the pipe_written variable was incremented. Thanks to88 * HP for finding this one. JRA.89 */90 91 if(set_blocking(select_pipe[0],0)==-1)92 smb_panic("select_pipe[0]: O_NONBLOCK failed");93 if(set_blocking(select_pipe[1],0)==-1)94 smb_panic("select_pipe[1]: O_NONBLOCK failed");95 96 initialised = sys_getpid();97 }98 99 ZERO_STRUCT(fds[num_fds]);100 fds[num_fds].fd = select_pipe[0];101 fds[num_fds].events = POLLIN|POLLHUP;102 103 errno = 0;104 ret = poll(fds, num_fds+1, timeout);105 106 if ((ret >= 0) && (fds[num_fds].revents & (POLLIN|POLLHUP|POLLERR))) {107 char c;108 int saved_errno = errno;109 110 if (read(select_pipe[0], &c, 1) == 1) {111 pipe_read += 1;112 113 /* Mark Weaver <mark-clist@npsl.co.uk> pointed out a critical114 fix to ensure we don't lose signals. We must always115 return -1 when the select pipe is set, otherwise if another116 fd is also ready (so ret == 2) then we used to eat the117 byte in the pipe and lose the signal. JRA.118 */119 ret = -1;120 #if 0121 /* JRA - we can use this to debug the signal messaging... */122 DEBUG(0,("select got %u signal\n", (unsigned int)c));123 #endif124 errno = EINTR;125 } else {126 ret -= 1;127 errno = saved_errno;128 }129 }130 131 return ret;132 }133 134 26 int sys_poll_intr(struct pollfd *fds, int num_fds, int timeout) 135 27 { … … 151 43 break; 152 44 } 45 /* Infinite timeout, no need to adjust. */ 46 if (timeout < 0) { 47 continue; 48 } 153 49 clock_gettime_mono(&now); 154 elapsed = nsec_time_diff(&now, &start); 155 timeout = (orig_timeout - elapsed) / 1000000; 50 elapsed = nsec_time_diff(&now, &start) / 1000000; 51 timeout = orig_timeout - elapsed; 52 /* Unlikely, but might happen eg. when getting traced. 53 * Make sure we're not hanging in this case. 54 */ 55 if (timeout < 0) { 56 timeout = 0; 57 } 156 58 }; 157 59 return ret;
Note:
See TracChangeset
for help on using the changeset viewer.