This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
static pid_t initialised;
static int select_pipe[2];
-static VOLATILE unsigned pipe_written, pipe_read;
+static volatile unsigned pipe_written, pipe_read;
/*******************************************************************
Call this from all Samba signal handlers if you want to avoid a
nasty signal race condition.
********************************************************************/
-void sys_select_signal(void)
+void sys_select_signal(char c)
{
- char c = 1;
if (!initialised) return;
if (pipe_written > pipe_read+256) return;
fd_set *readfds2, readfds_buf;
if (initialised != sys_getpid()) {
- pipe(select_pipe);
+ if (pipe(select_pipe) == -1)
+ {
+ DEBUG(0, ("sys_select: pipe failed (%s)\n",
+ strerror(errno)));
+ if (readfds != NULL)
+ FD_ZERO(readfds);
+ if (writefds != NULL)
+ FD_ZERO(writefds);
+ if (errorfds != NULL)
+ FD_ZERO(errorfds);
+ return -1;
+ }
/*
* These next two lines seem to fix a bug with the Linux
*/
if(set_blocking(select_pipe[0],0)==-1)
- smb_panic("select_pipe[0]: O_NONBLOCK failed.\n");
+ smb_panic("select_pipe[0]: O_NONBLOCK failed");
if(set_blocking(select_pipe[1],0)==-1)
- smb_panic("select_pipe[1]: O_NONBLOCK failed.\n");
+ smb_panic("select_pipe[1]: O_NONBLOCK failed");
initialised = sys_getpid();
}
FD_ZERO(writefds);
if (errorfds)
FD_ZERO(errorfds);
- }
-
- if (FD_ISSET(select_pipe[0], readfds2)) {
+ } else if (FD_ISSET(select_pipe[0], readfds2)) {
char c;
saved_errno = errno;
if (read(select_pipe[0], &c, 1) == 1) {
pipe_read++;
- }
- errno = saved_errno;
- FD_CLR(select_pipe[0], readfds2);
- ret--;
- if (ret == 0) {
+ /* Mark Weaver <mark-clist@npsl.co.uk> pointed out a critical
+ fix to ensure we don't lose signals. We must always
+ return -1 when the select pipe is set, otherwise if another
+ fd is also ready (so ret == 2) then we used to eat the
+ byte in the pipe and lose the signal. JRA.
+ */
ret = -1;
+#if 0
+ /* JRA - we can use this to debug the signal messaging... */
+ DEBUG(0,("select got %u signal\n", (unsigned int)c));
+#endif
errno = EINTR;
+ } else {
+ FD_CLR(select_pipe[0], readfds2);
+ ret--;
+ errno = saved_errno;
}
}
{
int ret;
fd_set *readfds2, readfds_buf, *writefds2, writefds_buf, *errorfds2, errorfds_buf;
- struct timeval tval2, *ptval;
+ struct timeval tval2, *ptval, end_time;
readfds2 = (readfds ? &readfds_buf : NULL);
writefds2 = (writefds ? &writefds_buf : NULL);
errorfds2 = (errorfds ? &errorfds_buf : NULL);
- ptval = (tval ? &tval2 : NULL);
+ if (tval) {
+ GetTimeOfDay(&end_time);
+ end_time.tv_sec += tval->tv_sec;
+ end_time.tv_usec += tval->tv_usec;
+ end_time.tv_sec += end_time.tv_usec / 1000000;
+ end_time.tv_usec %= 1000000;
+ errno = 0;
+ tval2 = *tval;
+ ptval = &tval2;
+ } else {
+ ptval = NULL;
+ }
do {
if (readfds)
writefds_buf = *writefds;
if (errorfds)
errorfds_buf = *errorfds;
- if (tval)
- tval2 = *tval;
+ if (ptval && (errno == EINTR)) {
+ struct timeval now_time;
+ int64_t tdif;
+
+ GetTimeOfDay(&now_time);
+ tdif = usec_time_diff(&end_time, &now_time);
+ if (tdif <= 0) {
+ ret = 0; /* time expired. */
+ break;
+ }
+ ptval->tv_sec = tdif / 1000000;
+ ptval->tv_usec = tdif % 1000000;
+ }
- ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval);
+ /* We must use select and not sys_select here. If we use
+ sys_select we'd lose the fact a signal occurred when sys_select
+ read a byte from the pipe. Fix from Mark Weaver
+ <mark-clist@npsl.co.uk>
+ */
+ ret = select(maxfd, readfds2, writefds2, errorfds2, ptval);
} while (ret == -1 && errno == EINTR);
if (readfds)