From b3eeabd77f585776ff803b7cec94705d2326b43d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Wed, 21 Jan 1998 12:05:34 -0800 Subject: [PATCH] select() and fdlib improved for NT Rev: src/backend.c:1.21 Rev: src/fdlib.c:1.7 Rev: src/fdlib.h:1.5 --- src/backend.c | 129 +++++++++++++++++++++++++++++++++++--------------- src/fdlib.c | 28 +++++++---- src/fdlib.h | 64 ++++++++++++++++++++++++- 3 files changed, 175 insertions(+), 46 deletions(-) diff --git a/src/backend.c b/src/backend.c index e0d8b7ce84..607a58c791 100644 --- a/src/backend.c +++ b/src/backend.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: backend.c,v 1.20 1998/01/02 01:05:41 hubbe Exp $"); +RCSID("$Id: backend.c,v 1.21 1998/01/21 20:05:32 hubbe Exp $"); #include "fdlib.h" #include "backend.h" #include <errno.h> @@ -35,8 +35,8 @@ RCSID("$Id: backend.c,v 1.20 1998/01/02 01:05:41 hubbe Exp $"); struct selectors { - fd_set read; - fd_set write; + my_fd_set read; + my_fd_set write; }; static struct selectors selectors; @@ -81,8 +81,8 @@ extern int pike_make_pipe(int *); void init_backend(void) { - fd_FD_ZERO(&selectors.read); - fd_FD_ZERO(&selectors.write); + my_FD_ZERO(&selectors.read); + my_FD_ZERO(&selectors.write); if(pike_make_pipe(wakeup_pipe) < 0) fatal("Couldn't create backend wakup pipe! errno=%d.\n",errno); set_nonblocking(wakeup_pipe[0],1); @@ -105,18 +105,18 @@ void set_read_callback(int fd,file_callback cb,void *data) if(cb) { - fd_FD_SET(fd, &selectors.read); + my_FD_SET(fd, &selectors.read); if(max_fd < fd) max_fd = fd; wake_up_backend(); }else{ if(fd <= max_fd) { - fd_FD_CLR(fd, &selectors.read); + my_FD_CLR(fd, &selectors.read); if(fd == max_fd) { while(max_fd >=0 && - !fd_FD_ISSET(max_fd, &selectors.read) && - !fd_FD_ISSET(max_fd, &selectors.write)) + !my_FD_ISSET(max_fd, &selectors.read) && + !my_FD_ISSET(max_fd, &selectors.write)) max_fd--; } } @@ -135,18 +135,18 @@ void set_write_callback(int fd,file_callback cb,void *data) if(cb) { - fd_FD_SET(fd, &selectors.write); + my_FD_SET(fd, &selectors.write); if(max_fd < fd) max_fd = fd; wake_up_backend(); }else{ if(fd <= max_fd) { - fd_FD_CLR(fd, &selectors.write); + my_FD_CLR(fd, &selectors.write); if(fd == max_fd) { while(max_fd >=0 && - !fd_FD_ISSET(max_fd, &selectors.read) && - !fd_FD_ISSET(max_fd, &selectors.write)) + !my_FD_ISSET(max_fd, &selectors.read) && + !my_FD_ISSET(max_fd, &selectors.write)) max_fd--; } } @@ -219,7 +219,7 @@ void do_debug(void) for(e=0;e<=max_fd;e++) { - if(fd_FD_ISSET(e,&selectors.read) || fd_FD_ISSET(e,&selectors.write)) + if(my_FD_ISSET(e,&selectors.read) || my_FD_ISSET(e,&selectors.write)) { int ret; do { @@ -247,7 +247,8 @@ void backend(void) { JMP_BUF back; int i, delay; - struct selectors sets; + fd_set rset; + fd_set wset; if(SETJMP(back)) { @@ -270,7 +271,8 @@ void backend(void) check_threads_etc(); - sets=selectors; + fd_copy_my_fd_set_to_fd_set(&rset, &selectors.read, max_fd+1); + fd_copy_my_fd_set_to_fd_set(&wset, &selectors.write, max_fd+1); alloca(0); /* Do garbage collect */ #ifdef DEBUG @@ -288,7 +290,7 @@ void backend(void) } THREADS_ALLOW(); - i=fd_select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout); + i=fd_select(max_fd+1, &rset, &wset, 0, &next_timeout); GETTIMEOFDAY(¤t_time); THREADS_DISALLOW(); may_need_wakeup=0; @@ -297,45 +299,92 @@ void backend(void) { for(i=0; i<max_fd+1; i++) { - if(fd_FD_ISSET(i, &sets.read) && read_callback[i]) + if(fd_FD_ISSET(i, &rset) && read_callback[i]) (*(read_callback[i]))(i,read_callback_data[i]); - if(fd_FD_ISSET(i, &sets.write) && write_callback[i]) + if(fd_FD_ISSET(i, &wset) && write_callback[i]) (*(write_callback[i]))(i,write_callback_data[i]); } }else{ switch(errno) { +#ifdef __NT__ + default: + fatal("Error in backend %d\n",errno); + break; +#endif + case EINVAL: fatal("Invalid timeout to select().\n"); break; +#ifdef WSAEINTR + case WSAEINTR: +#endif case EINTR: /* ignore */ break; +#ifdef WSAEBADF + case WSAEBADF: +#endif +#ifdef WSAENOTSOCK + case WSAENOTSOCK: +#endif case EBADF: - sets=selectors; + + fd_copy_my_fd_set_to_fd_set(&rset, &selectors.read, max_fd+1); + fd_copy_my_fd_set_to_fd_set(&wset, &selectors.write, max_fd+1); next_timeout.tv_usec=0; next_timeout.tv_sec=0; - if(fd_select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout) < 0 && errno == EBADF) + if(fd_select(max_fd+1, &rset, &wset, 0, &next_timeout) < 0) { - int i; - for(i=0;i<MAX_OPEN_FILEDESCRIPTORS;i++) + switch(errno) { - if(!fd_FD_ISSET(i, &selectors.read) && !FD_ISSET(i,&selectors.write)) - continue; - - fd_FD_ZERO(& sets.read); - fd_FD_ZERO(& sets.write); - - if(fd_FD_ISSET(i, &selectors.read)) fd_FD_SET(i, &sets.read); - if(fd_FD_ISSET(i, &selectors.write)) fd_FD_SET(i, &sets.write); - - next_timeout.tv_usec=0; - next_timeout.tv_sec=0; - - if(select(max_fd+1, &sets.read, &sets.write, 0, &next_timeout) < 0 && errno == EBADF) - fatal("Filedescriptor %d caused EBADF.\n",i); +#ifdef WSAEBADF + case WSAEBADF: +#endif +#ifdef WSAENOTSOCK + case WSAENOTSOCK: +#endif + case EBADF: + { + int i; + for(i=0;i<MAX_OPEN_FILEDESCRIPTORS;i++) + { + if(!my_FD_ISSET(i, &selectors.read) && !my_FD_ISSET(i,&selectors.write)) + continue; + + fd_FD_ZERO(& rset); + fd_FD_ZERO(& wset); + + if(my_FD_ISSET(i, &selectors.read)) fd_FD_SET(i, &rset); + if(my_FD_ISSET(i, &selectors.write)) fd_FD_SET(i, &wset); + + next_timeout.tv_usec=0; + next_timeout.tv_sec=0; + + if(fd_select(max_fd+1, &rset, &wset, 0, &next_timeout) < 0) + { + switch(errno) + { +#ifdef __NT__ + default: +#endif + case EBADF: +#ifdef WSAEBADF + case WSAEBADF: +#endif +#ifdef WSAENOTSOCK + case WSAENOTSOCK: +#endif + fatal("Filedescriptor %d (%s) caused fatal error %d in backend.\n",i,fd_info(i),errno); + + case EINTR: + break; + } + } + } + } } #ifdef _REENTRANT write_to_stderr("Bad filedescriptor to select().\n" @@ -356,6 +405,11 @@ void backend(void) int write_to_stderr(char *a, INT32 len) { +#ifdef __NT__ + int e; + for(e=0;e<len;e++) + putc(a[e],stderr); +#else int nonblock=0; INT32 pos, tmp; @@ -386,6 +440,7 @@ int write_to_stderr(char *a, INT32 len) if(nonblock) set_nonblocking(2,1); +#endif return 1; } diff --git a/src/fdlib.c b/src/fdlib.c index 58717235a6..0053573e5c 100644 --- a/src/fdlib.c +++ b/src/fdlib.c @@ -3,17 +3,29 @@ #ifdef HAVE_WINSOCK2_H -#define FD_SOCKET -4 -#define FD_CONSOLE -3 -#define FD_FILE -2 -#define FD_NO_MORE_FREE -1 - long da_handle[MAX_OPEN_FILEDESCRIPTORS]; -static int fd_type[MAX_OPEN_FILEDESCRIPTORS]; +int fd_type[MAX_OPEN_FILEDESCRIPTORS]; int first_free_handle; #define FDDEBUG(X) +char *fd_info(int fd) +{ + if(fd<0) + return "BAD"; + + if(fd > MAX_OPEN_FILEDESCRIPTORS) + return "OUT OF RANGE"; + + switch(fd_type[fd]) + { + case FD_SOCKET: return "IS SOCKET"; + case FD_CONSOLE: return "IS CONSOLE"; + case FD_FILE: return "IS FILE"; + default: return "NOT OPEN"; + } +} + void fd_init() { int e; @@ -174,7 +186,7 @@ FD fd_accept(FD fd, struct sockaddr *addr, int *addrlen) } #define SOCKFUN(NAME,X1,X2) \ -int PIKE_CONCAT(fd_,NAME) X1 { int ret; \ +int PIKE_CONCAT(fd_,NAME) X1 { SOCKET ret; \ FDDEBUG(fprintf(stderr, #NAME " on %d (%d)\n",fd,da_handle[fd])); \ if(fd_type[fd] != FD_SOCKET) { \ errno=ENOTSUPP; \ @@ -183,7 +195,7 @@ int PIKE_CONCAT(fd_,NAME) X1 { int ret; \ ret=NAME X2; \ if(ret == SOCKET_ERROR) errno=WSAGetLastError(); \ FDDEBUG(fprintf(stderr, #NAME " returned %d (%d)\n",ret,errno)); \ - return ret; \ + return (int)ret; \ } #define SOCKFUN1(NAME,T1) \ diff --git a/src/fdlib.h b/src/fdlib.h index 4ce802b05e..b2ddd7aa63 100644 --- a/src/fdlib.h +++ b/src/fdlib.h @@ -2,6 +2,7 @@ #define FDLIB_H #include "global.h" +#include "pike_macros.h" #ifdef HAVE_ERRNO_H #include <errno.h> @@ -38,6 +39,7 @@ typedef int FD; #define SOCKFUN5(NAME,T1,T2,T3,T4,T5) int PIKE_CONCAT(fd_,NAME) (FD,T1,T2,T3,T4,T5); /* Prototypes begin here */ +char *fd_info(int fd); void fd_init(); void fd_exit(); FD fd_open(char *file, int open_mode, int create_mode); @@ -99,10 +101,54 @@ FD fd_dup2(FD from, FD to); #define fd_shutdown_write SD_SEND #define fd_shutdown_both SD_BOTH +#define FD_SOCKET -4 +#define FD_CONSOLE -3 +#define FD_FILE -2 +#define FD_NO_MORE_FREE -1 + + +typedef struct my_fd_set_s +{ + char bits[MAX_OPEN_FILEDESCRIPTORS/8]; +} my_fd_set; + +#ifdef DEBUG +#define fd_check_fd(X) do { if(fd_type[X]>=0) fatal("FD_SET on closed fd %d (%d) %s:%d.\n",X,da_handle[X],__FILE__,__LINE__); }while(0) +#else +#define fd_check_fd(X) +#endif +#define my_FD_CLR(FD,S) ((S)->bits[(FD)>>3]&=~ (1<<(FD&7))) +#define my_FD_SET(FD,S) do{ fd_check_fd(FD); ((S)->bits[(FD)>>3]|= (1<<(FD&7))); }while(0) +#define my_FD_ISSET(FD,S) ((S)->bits[(FD)>>3]&(1<<(FD&7))) +#define my_FD_ZERO(S) MEMSET(& (S)->bits, 0, sizeof(my_fd_set)) + +#define fd_copy_my_fd_set_to_fd_set(TO,FROM,max) do { \ + int e_,d_,max_=MINIMUM(MAX_OPEN_FILEDESCRIPTORS>>3,(max+7)>>3); \ + (TO)->fd_count=0; \ + for(e_=0;e_<max_;e_++) \ + { \ + int b_=(FROM)->bits[e_]; \ + if(b_) \ + { \ + for(d_=0;d_<8;d_++) \ + { \ + if(b_ & (1<<d_)) \ + { \ + int fd_=(e_<<3)+d_; \ + fd_check_fd(fd_); \ + (TO)->fd_array[(TO)->fd_count++]=(SOCKET)da_handle[fd_]; \ + } \ + } \ + } \ + } \ +}while(0) + extern long da_handle[MAX_OPEN_FILEDESCRIPTORS]; +extern int fd_type[MAX_OPEN_FILEDESCRIPTORS]; #define fd_FD_CLR(X,Y) FD_CLR((SOCKET)da_handle[X],Y) -#define fd_FD_SET(X,Y) FD_SET((SOCKET)da_handle[X],Y) +#define fd_FD_SET(X,Y) \ + do { fd_check_fd(X); FD_SET((SOCKET)da_handle[X],Y); }while(0) #define fd_FD_ISSET(X,Y) FD_ISSET((SOCKET)da_handle[X],Y) #define fd_FD_ZERO(X) FD_ZERO(X) @@ -115,6 +161,7 @@ extern long da_handle[MAX_OPEN_FILEDESCRIPTORS]; typedef int FD; +#define fd_info(X) "" #define fd_init() #define fd_exit() @@ -151,6 +198,8 @@ typedef int FD; #define fd_listen listen #define fd_select select + +#define fd_fd_set fd_set #define fd_FD_CLR FD_CLR #define fd_FD_SET FD_SET #define fd_FD_ISSET FD_ISSET @@ -160,6 +209,19 @@ typedef int FD; #define fd_shutdown_write 1 #define fd_shutdown_both 2 +typedef struct my_fd_set_s +{ + fd_set tmp; +} my_fd_set; + +#define my_FD_CLR(FD,S) FD_CLR((FD), & (S)->tmp) +#define my_FD_SET(FD,S) FD_SET((FD), & (S)->tmp) +#define my_FD_ISSET(FD,S) FD_ISSET((FD), & (S)->tmp) +#define my_FD_ZERO(S) FD_ZERO(& (S)->tmp) + +#define fd_copy_my_fd_set_to_fd_set(TO,FROM,max) \ + MEMCPY((TO),&(FROM)->tmp,sizeof(*(TO))) + #endif #endif -- GitLab