1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-25 00:23:52 +03:00

Fix from Michael Steffens <michael_steffens@hp.com> to make signal

processing work correctly in winbindd. This is a really good patch
that gives full select semantics to the Samba modified select.
Jeremy.
This commit is contained in:
Jeremy Allison
-
parent 9c8a2fe4df
commit 3af16ade17
13 changed files with 71 additions and 36 deletions

View File

@@ -2169,7 +2169,7 @@ static void readline_callback(void)
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = 0; timeout.tv_usec = 0;
sys_select_intr(cli->fd+1,&fds,&timeout); sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
/* We deliberately use receive_smb instead of /* We deliberately use receive_smb instead of
client_receive_smb as we want to receive client_receive_smb as we want to receive

View File

@@ -51,7 +51,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void),
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(fd,&fds); FD_SET(fd,&fds);
if (sys_select_intr(fd+1,&fds,&timeout) == 1) { if (sys_select_intr(fd+1,&fds,NULL,NULL,&timeout) == 1) {
ret = fgets(line, sizeof(line), stdin); ret = fgets(line, sizeof(line), stdin);
return ret; return ret;
} }

View File

@@ -1,5 +1,6 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/Netbios implementation.
Version 3.0
Samba select/poll implementation Samba select/poll implementation
Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Andrew Tridgell 1992-1998
@@ -20,22 +21,23 @@
#include "includes.h" #include "includes.h"
/* this is here because it allows us to avoid a nasty race in signal handling. /* This is here because it allows us to avoid a nasty race in signal handling.
We need to guarantee that when we get a signal we get out of a select immediately We need to guarantee that when we get a signal we get out of a select immediately
but doing that involves a race condition. We can avoid the race by getting the but doing that involves a race condition. We can avoid the race by getting the
signal handler to write to a pipe that is in the select/poll list signal handler to write to a pipe that is in the select/poll list
this means all Samba signal handlers should call sys_select_signal() This means all Samba signal handlers should call sys_select_signal().
*/ */
static pid_t initialised; static pid_t initialised;
static int select_pipe[2]; 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 Call this from all Samba signal handlers if you want to avoid a
nasty signal race condition nasty signal race condition.
********************************************************************/ ********************************************************************/
void sys_select_signal(void) void sys_select_signal(void)
{ {
char c = 1; char c = 1;
@@ -47,13 +49,15 @@ void sys_select_signal(void)
} }
/******************************************************************* /*******************************************************************
like select() but avoids the signal race using a pipe Like select() but avoids the signal race using a pipe
it also guarantees that fds on return only ever contains bits set it also guuarantees that fds on return only ever contains bits set
for file descriptors that were readable for file descriptors that were readable.
********************************************************************/ ********************************************************************/
int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval)
{ {
int ret, saved_errno; int ret, saved_errno;
fd_set *readfds2, readfds_buf;
if (initialised != sys_getpid()) { if (initialised != sys_getpid()) {
pipe(select_pipe); pipe(select_pipe);
@@ -76,16 +80,29 @@ int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
} }
maxfd = MAX(select_pipe[0]+1, maxfd); maxfd = MAX(select_pipe[0]+1, maxfd);
FD_SET(select_pipe[0], fds);
/* If readfds is NULL we need to provide our own set. */
if (readfds) {
readfds2 = readfds;
} else {
readfds2 = &readfds_buf;
FD_ZERO(readfds2);
}
FD_SET(select_pipe[0], readfds2);
errno = 0; errno = 0;
ret = select(maxfd,fds,NULL,NULL,tval); ret = select(maxfd,readfds2,writefds,errorfds,tval);
if (ret <= 0) { if (ret <= 0) {
FD_ZERO(fds); FD_ZERO(readfds2);
if (writefds)
FD_ZERO(writefds);
if (errorfds)
FD_ZERO(errorfds);
} }
if (FD_ISSET(select_pipe[0], fds)) { if (FD_ISSET(select_pipe[0], readfds2)) {
FD_CLR(select_pipe[0], fds); FD_CLR(select_pipe[0], readfds2);
ret--; ret--;
if (ret == 0) { if (ret == 0) {
ret = -1; ret = -1;
@@ -109,20 +126,35 @@ int sys_select(int maxfd, fd_set *fds,struct timeval *tval)
} }
/******************************************************************* /*******************************************************************
similar to sys_select() but catch EINTR and continue Similar to sys_select() but catch EINTR and continue.
this is what sys_select() used to do in Samba This is what sys_select() used to do in Samba.
********************************************************************/ ********************************************************************/
int sys_select_intr(int maxfd, fd_set *fds,struct timeval *tval)
int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *tval)
{ {
int ret; int ret;
fd_set fds2; fd_set *readfds2, readfds_buf, *writefds2, writefds_buf, *errorfds2, errorfds_buf;
readfds2 = (readfds ? &readfds_buf : NULL);
writefds2 = (writefds ? &writefds_buf : NULL);
errorfds2 = (errorfds ? &errorfds_buf : NULL);
do { do {
fds2 = *fds; if (readfds)
ret = sys_select(maxfd, &fds2, tval); readfds_buf = *readfds;
if (writefds)
writefds_buf = *writefds;
if (errorfds)
errorfds_buf = *errorfds;
ret = sys_select(maxfd, readfds2, writefds2, errorfds2, tval);
} while (ret == -1 && errno == EINTR); } while (ret == -1 && errno == EINTR);
*fds = fds2; if (readfds)
*readfds = readfds_buf;
if (writefds)
*writefds = writefds_buf;
if (errorfds)
*errorfds = errorfds_buf;
return ret; return ret;
} }

View File

@@ -642,7 +642,7 @@ void msleep(int t)
FD_ZERO(&fds); FD_ZERO(&fds);
errno = 0; errno = 0;
sys_select_intr(0,&fds,&tval); sys_select_intr(0,&fds,NULL,NULL,&tval);
GetTimeOfDay(&t2); GetTimeOfDay(&t2);
tdiff = TvalDiff(&t1,&t2); tdiff = TvalDiff(&t1,&t2);

View File

@@ -208,7 +208,7 @@ int read_data_outstanding(int fd, unsigned int time_out)
timeout.tv_sec = (time_t) (time_out / 1000); timeout.tv_sec = (time_t) (time_out / 1000);
timeout.tv_usec = (long)(1000 * (time_out % 1000)); timeout.tv_usec = (long)(1000 * (time_out % 1000));
selrtn = sys_select_intr(fd + 1, &fds, &timeout); selrtn = sys_select_intr(fd + 1, &fds, NULL, NULL, &timeout);
if (selrtn <= 0) if (selrtn <= 0)
{ {
@@ -283,7 +283,7 @@ static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t ma
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(fd,&fds); FD_SET(fd,&fds);
selrtn = sys_select_intr(fd+1,&fds,&timeout); selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout);
/* Check if error */ /* Check if error */
if (selrtn == -1) { if (selrtn == -1) {

View File

@@ -952,7 +952,7 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
timeout.tv_sec = t/1000; timeout.tv_sec = t/1000;
timeout.tv_usec = 1000*(t%1000); timeout.tv_usec = 1000*(t%1000);
if ((ret = sys_select_intr(fd+1,&fds,&timeout)) == -1) { if ((ret = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout)) == -1) {
/* errno should be EBADF or EINVAL. */ /* errno should be EBADF or EINVAL. */
DEBUG(0,("select returned -1, errno = %s (%d)\n", strerror(errno), errno)); DEBUG(0,("select returned -1, errno = %s (%d)\n", strerror(errno), errno));
return NULL; return NULL;

View File

@@ -1817,7 +1817,7 @@ BOOL listen_for_packets(BOOL run_election)
BlockSignals(False, SIGTERM); BlockSignals(False, SIGTERM);
selrtn = sys_select(FD_SETSIZE,&fds,&timeout); selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout);
/* We can only take signals when we are in the select - block them again here. */ /* We can only take signals when we are in the select - block them again here. */

View File

@@ -168,6 +168,7 @@ static BOOL do_sigterm;
static void termination_handler(int signum) static void termination_handler(int signum)
{ {
do_sigterm = True; do_sigterm = True;
sys_select_signal();
} }
static BOOL do_sigusr2; static BOOL do_sigusr2;
@@ -175,6 +176,7 @@ static BOOL do_sigusr2;
static void sigusr2_handler(int signum) static void sigusr2_handler(int signum)
{ {
do_sigusr2 = True; do_sigusr2 = True;
sys_select_signal();
} }
static BOOL do_sighup; static BOOL do_sighup;
@@ -182,6 +184,7 @@ static BOOL do_sighup;
static void sighup_handler(int signum) static void sighup_handler(int signum)
{ {
do_sighup = True; do_sighup = True;
sys_select_signal();
} }
/* Create winbindd socket */ /* Create winbindd socket */
@@ -553,7 +556,7 @@ static void process_loop(int accept_sock)
/* Call select */ /* Call select */
selret = select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout);
if (selret == 0) if (selret == 0)
continue; continue;

View File

@@ -93,7 +93,7 @@ BOOL receive_local_message(fd_set *fds, char *buffer, int buffer_len, int timeou
to.tv_sec = timeout / 1000; to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000; to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(maxfd+1,fds,&to); selrtn = sys_select(maxfd+1,fds,NULL,NULL,&to);
if (selrtn == -1 && errno == EINTR) { if (selrtn == -1 && errno == EINTR) {
/* could be a kernel oplock interrupt */ /* could be a kernel oplock interrupt */

View File

@@ -193,7 +193,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
to.tv_sec = timeout / 1000; to.tv_sec = timeout / 1000;
to.tv_usec = (timeout % 1000) * 1000; to.tv_usec = (timeout % 1000) * 1000;
selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,timeout>0?&to:NULL); selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,timeout>0?&to:NULL);
/* if we get EINTR then maybe we have received an oplock /* if we get EINTR then maybe we have received an oplock
signal - treat this as select returning 1. This is ugly, but signal - treat this as select returning 1. This is ugly, but

View File

@@ -239,7 +239,7 @@ max can be %d\n",
memcpy((char *)&lfds, (char *)&listen_set, memcpy((char *)&lfds, (char *)&listen_set,
sizeof(listen_set)); sizeof(listen_set));
num = sys_select(FD_SETSIZE,&lfds,NULL); num = sys_select(FD_SETSIZE,&lfds,NULL,NULL,NULL);
if (num == -1 && errno == EINTR) { if (num == -1 && errno == EINTR) {
extern VOLATILE sig_atomic_t reload_after_sighup; extern VOLATILE sig_atomic_t reload_after_sighup;

View File

@@ -137,7 +137,7 @@ static void filter_child(int c, struct in_addr dest_ip)
if (s != -1) FD_SET(s, &fds); if (s != -1) FD_SET(s, &fds);
if (c != -1) FD_SET(c, &fds); if (c != -1) FD_SET(c, &fds);
num = sys_select_intr(MAX(s+1, c+1),&fds,NULL); num = sys_select_intr(MAX(s+1, c+1),&fds,NULL,NULL,NULL);
if (num <= 0) continue; if (num <= 0) continue;
if (c != -1 && FD_ISSET(c, &fds)) { if (c != -1 && FD_ISSET(c, &fds)) {
@@ -201,7 +201,7 @@ static void start_filter(char *desthost)
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(s, &fds); FD_SET(s, &fds);
num = sys_select_intr(s+1,&fds,NULL); num = sys_select_intr(s+1,&fds,NULL,NULL,NULL);
if (num > 0) { if (num > 0) {
c = accept(s, &addr, &in_addrlen); c = accept(s, &addr, &in_addrlen);
if (c != -1) { if (c != -1) {

View File

@@ -380,7 +380,7 @@ static BOOL listen_for_wins_packets(void)
BlockSignals(False, SIGTERM); BlockSignals(False, SIGTERM);
num = sys_select(FD_SETSIZE, &fds, &timeout); num = sys_select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
/* We can only take signals when we are in the select - block them again here. */ /* We can only take signals when we are in the select - block them again here. */