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(&current_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