From ef1e937a45bd883ecb1d67455faa796038734b5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Thu, 26 Mar 1998 15:31:03 +0100
Subject: [PATCH] Improved _disable_threads(). Added THREADS_ALLOW_UID() and
 THREADS_DISALLOW_UID().

Rev: src/modules/files/efuns.c:1.47
Rev: src/modules/files/file.c:1.83
Rev: src/modules/files/socket.c:1.30
Rev: src/modules/spider/dumudp.c:1.36
Rev: src/modules/system/passwords.c:1.7
Rev: src/modules/system/syslog.c:1.5
Rev: src/modules/system/system.c:1.47
Rev: src/program.c:1.67
Rev: src/threads.c:1.65
Rev: src/threads.h:1.37
---
 src/modules/files/efuns.c      | 31 ++++++++++++++---------
 src/modules/files/file.c       |  6 ++---
 src/modules/files/socket.c     |  4 +--
 src/modules/spider/dumudp.c    |  6 ++++-
 src/modules/system/passwords.c | 29 ++++++++++++++++++---
 src/modules/system/syslog.c    |  8 ++++--
 src/modules/system/system.c    | 24 +++++++++---------
 src/program.c                  |  3 ++-
 src/threads.c                  | 15 ++++++++++-
 src/threads.h                  | 46 +++++++++++++++++++++++++++++++---
 10 files changed, 131 insertions(+), 41 deletions(-)

diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c
index a1c76d0981..5bcbf5b2c8 100644
--- a/src/modules/files/efuns.c
+++ b/src/modules/files/efuns.c
@@ -60,11 +60,13 @@
 # endif
 #endif
 
+#include "dmalloc.h"
+
 #ifdef HAVE_PROCESS_H
 #include <process.h>
 #endif
 
-#include "dmalloc.h"
+/* #define DEBUG_FILE */
 
 struct array *encode_stat(struct stat *s)
 {
@@ -78,7 +80,12 @@ struct array *encode_stat(struct stat *s)
 #ifdef S_IFLNK
   case S_IFLNK: ITEM(a)[1].u.integer=-3; break;
 #endif
-  default: ITEM(a)[1].u.integer=-4; break;
+  default:
+#ifdef DEBUG_FILE
+    fprintf(stderr, "encode_stat(): mode:%ld\n", (long)S_IFMT & s->st_mode);
+#endif /* DEBUG_FILE */
+    ITEM(a)[1].u.integer=-4;
+    break;
   }
   ITEM(a)[2].u.integer=s->st_atime;
   ITEM(a)[3].u.integer=s->st_mtime;
@@ -102,7 +109,7 @@ void f_file_stat(INT32 args)
 
   s = sp[-args].u.string->str;
   l = (args>1 && !IS_ZERO(sp-1-args))?1:0;
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
 #ifdef HAVE_LSTAT
   if(l)
     i=lstat(s, &st);
@@ -110,7 +117,7 @@ void f_file_stat(INT32 args)
 #endif
     i=stat(s, &st);
 
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
   pop_n_elems(args);
   if(i==-1)
   {
@@ -326,7 +333,7 @@ void f_rm(INT32 args)
 
   s = sp[-args].u.string->str;
   
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
 #ifdef HAVE_LSTAT
   i=lstat(s, &st) != -1;
 #else
@@ -341,7 +348,7 @@ void f_rm(INT32 args)
       i=unlink(s) != -1;
     }
   }
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
       
   pop_n_elems(args);
   push_int(i);
@@ -367,13 +374,13 @@ void f_mkdir(INT32 args)
     i=sp[1-args].u.integer;
   }
   s=sp[-args].u.string->str;
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
 #if MKDIR_ARGS == 2
   i=mkdir(s, i) != -1;
 #else
   i=mkdir(s) != -1;
 #endif
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
   pop_n_elems(args);
   push_int(i);
 }
@@ -395,9 +402,9 @@ void f_get_dir(INT32 args)
   get_all_args("get_dir",args,"%s",&path);
 
 #if defined(_REENTRANT) && defined(HAVE_READDIR_R)
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   dir=opendir(path);
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
   if(dir)
   {
 #define FPR 1024
@@ -561,9 +568,9 @@ void f_getcwd(INT32 args)
 #define MAXPATHLEN 32768
 #endif
   tmp=xalloc(MAXPATHLEN+1);
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   e=(char *)getwd(tmp);
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
 #endif
   if(!e) {
     if (tmp) 
diff --git a/src/modules/files/file.c b/src/modules/files/file.c
index 518dd81e33..b4d51c9ed2 100644
--- a/src/modules/files/file.c
+++ b/src/modules/files/file.c
@@ -6,7 +6,7 @@
 #define READ_BUFFER 8192
 
 #include "global.h"
-RCSID("$Id: file.c,v 1.82 1998/03/26 03:12:39 hubbe Exp $");
+RCSID("$Id: file.c,v 1.83 1998/03/26 14:31:01 grubba Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -882,11 +882,11 @@ static void file_open(INT32 args)
   if(!( flags &  (FILE_READ | FILE_WRITE)))
     error("Must open file for at least one of read and write.\n");
 
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   do {
     fd=fd_open(str->str,map(flags), access);
   } while(fd < 0 && errno == EINTR);
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
 
   if(!fp->current_object->prog)
     error("Object destructed in file->open()\n");
diff --git a/src/modules/files/socket.c b/src/modules/files/socket.c
index fa157f8daf..8b103fc6e6 100644
--- a/src/modules/files/socket.c
+++ b/src/modules/files/socket.c
@@ -229,9 +229,9 @@ static void port_bind(INT32 args)
   addr.sin_port = htons( ((u_short)sp[-args].u.integer) );
   addr.sin_family = AF_INET;
 
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   tmp=fd_bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0 || fd_listen(fd, 5) < 0;
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
 
   if(tmp)
   {
diff --git a/src/modules/spider/dumudp.c b/src/modules/spider/dumudp.c
index d86d8976cb..1f1461ce21 100644
--- a/src/modules/spider/dumudp.c
+++ b/src/modules/spider/dumudp.c
@@ -1,7 +1,7 @@
 #include "config.h"
 
 #include "global.h"
-RCSID("$Id: dumudp.c,v 1.35 1998/03/12 18:44:30 per Exp $");
+RCSID("$Id: dumudp.c,v 1.36 1998/03/26 14:31:02 grubba Exp $");
 #include "fdlib.h"
 #include "interpret.h"
 #include "svalue.h"
@@ -136,8 +136,12 @@ static void udp_bind(INT32 args)
   addr.sin_port = htons( ((u_short)sp[-args].u.integer) );
   addr.sin_family = AF_INET;
 
+  THREADS_ALLOW_UID();
+
   tmp=fd_bind(fd, (struct sockaddr *)&addr, sizeof(addr))<0;
 
+  THREADS_DISALLOW_UID();
+
   if(tmp)
   {
     fd_close(fd);
diff --git a/src/modules/system/passwords.c b/src/modules/system/passwords.c
index 6f962d781c..55ecf970b1 100644
--- a/src/modules/system/passwords.c
+++ b/src/modules/system/passwords.c
@@ -1,5 +1,5 @@
 /*
- * $Id: passwords.c,v 1.6 1998/03/03 10:51:37 mast Exp $
+ * $Id: passwords.c,v 1.7 1998/03/26 14:31:02 grubba Exp $
  *
  * Password handling for Pike.
  *
@@ -15,7 +15,7 @@
 
 #include "global.h"
 
-RCSID("$Id: passwords.c,v 1.6 1998/03/03 10:51:37 mast Exp $");
+RCSID("$Id: passwords.c,v 1.7 1998/03/26 14:31:02 grubba Exp $");
 
 #include "module_support.h"
 #include "interpret.h"
@@ -59,7 +59,10 @@ static void push_pwent(struct passwd *ent)
   if(!strcmp(ent->pw_passwd, "x"))
   {
     struct spwd *foo;
-    if((foo = getspnam(ent->pw_name)))
+    THREADS_ALLOW_UID();
+    foo = getspnam(ent->pw_name);
+    THREADS_DISALLOW_UID();
+    if(foo)
       push_text(foo->sp_pwdp);
     else
       push_text("x");
@@ -103,7 +106,9 @@ void f_getgrgid(INT32 args)
   int gid;
   struct group *foo;
   get_all_args("getgrgid", args, "%d", &gid);
+  THREADS_ALLOW_UID();
   foo = getgrgid( gid );
+  THREADS_DISALLOW_UID();
   pop_n_elems( args );
   push_grent( foo );
 }
@@ -116,7 +121,9 @@ void f_getgrnam(INT32 args)
   char *str;
   struct group *foo;
   get_all_args("getgrnam", args, "%s", &str);
+  THREADS_ALLOW_UID();
   foo = getgrnam( str );
+  THREADS_DISALLOW_UID();
   pop_n_elems( args );
   push_grent( foo );
 }
@@ -131,7 +138,9 @@ void f_getpwnam(INT32 args)
 
   get_all_args("getpwnam", args, "%s", &str);
 
+  THREADS_ALLOW_UID();
   foo = getpwnam(str);
+  THREADS_DISALLOW_UID();
 
   pop_n_elems(args);
   push_pwent(foo);
@@ -147,7 +156,9 @@ void f_getpwuid(INT32 args)
   
   get_all_args("getpwuid", args, "%i", &uid);
 
+  THREADS_ALLOW_UID();
   foo = getpwuid(uid);
+  THREADS_DISALLOW_UID();
 
   pop_n_elems(args);
   push_pwent(foo);
@@ -158,7 +169,9 @@ void f_getpwuid(INT32 args)
 /* int setpwent() */
 void f_setpwent(INT32 args)
 {
+  THREADS_ALLOW();
   setpwent();
+  THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
 }
@@ -168,7 +181,9 @@ void f_setpwent(INT32 args)
 /* int endpwent() */
 void f_endpwent(INT32 args)
 {
+  THREADS_ALLOW();
   endpwent();
+  THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
 }
@@ -180,7 +195,9 @@ void f_getpwent(INT32 args)
 {
   struct passwd *foo;
   pop_n_elems(args);
+  THREADS_ALLOW_UID();
   foo = getpwent();
+  THREADS_DISALLOW_UID();
   if(!foo)
   {
     push_int(0);
@@ -194,7 +211,9 @@ void f_getpwent(INT32 args)
 /* int setgrent() */
 void f_setgrent(INT32 args)
 {
+  THREADS_ALLOW();
   setgrent();
+  THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
 }
@@ -204,7 +223,9 @@ void f_setgrent(INT32 args)
 /* int endgrent() */
 void f_endgrent(INT32 args)
 {
+  THREADS_ALLOW();
   endgrent();
+  THREADS_DISALLOW();
   pop_n_elems(args);
   push_int(0);
 }
@@ -216,7 +237,9 @@ void f_getgrent(INT32 args)
 {
   struct group *foo;
   pop_n_elems(args);
+  THREADS_ALLOW_UID();
   foo = getgrent();
+  THREADS_DISALLOW_UID();
   if(!foo)
   {
     push_int(0);
diff --git a/src/modules/system/syslog.c b/src/modules/system/syslog.c
index 9249e80da6..972e24937b 100644
--- a/src/modules/system/syslog.c
+++ b/src/modules/system/syslog.c
@@ -1,5 +1,5 @@
 /*
- * $Id: syslog.c,v 1.4 1997/12/07 21:59:15 grubba Exp $
+ * $Id: syslog.c,v 1.5 1998/03/26 14:31:02 grubba Exp $
  *
  * Access to syslog from Pike.
  *
@@ -17,7 +17,7 @@
 
 #ifdef HAVE_SYSLOG
 
-RCSID("$Id: syslog.c,v 1.4 1997/12/07 21:59:15 grubba Exp $");
+RCSID("$Id: syslog.c,v 1.5 1998/03/26 14:31:02 grubba Exp $");
 
 #include "interpret.h"
 #include "svalue.h"
@@ -135,9 +135,13 @@ void f_openlog(INT32 args)
   if(p_facility & (1<<16)) facility |= LOG_SYSLOG;
   if(p_facility & (1<<17)) facility |= LOG_USER;
   if(p_facility & (1<<18)) facility |= LOG_UUCP;
+
+  THREADS_ALLOW();
   
   openlog(ident, option, facility);
 
+  THREADS_DISALLOW();
+
   pop_n_elems(args);
 }
  
diff --git a/src/modules/system/system.c b/src/modules/system/system.c
index 34c7b7b7d8..5551153f7e 100644
--- a/src/modules/system/system.c
+++ b/src/modules/system/system.c
@@ -1,5 +1,5 @@
 /*
- * $Id: system.c,v 1.46 1998/03/26 00:52:48 hubbe Exp $
+ * $Id: system.c,v 1.47 1998/03/26 14:31:03 grubba Exp $
  *
  * System-call module for Pike
  *
@@ -14,7 +14,7 @@
 #include "system.h"
 
 #include "global.h"
-RCSID("$Id: system.c,v 1.46 1998/03/26 00:52:48 hubbe Exp $");
+RCSID("$Id: system.c,v 1.47 1998/03/26 14:31:03 grubba Exp $");
 #ifdef HAVE_WINSOCK_H
 #include <winsock.h>
 #endif
@@ -172,11 +172,11 @@ void f_hardlink(INT32 args)
 
   get_all_args("hardlink",args, "%s%s", &from, &to);
 
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   do {
     err = link(from, to);
   } while ((err < 0) && (errno == EINTR));
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
 
   if (err < 0) {
     report_error("hardlink");
@@ -195,11 +195,11 @@ void f_symlink(INT32 args)
 
   get_all_args("symlink",args, "%s%s", &from, &to);
 
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   do {
     err = symlink(from, to);
   } while ((err < 0) && (errno == EINTR));
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
 
   if (err < 0) {
     report_error("symlink");
@@ -227,11 +227,11 @@ void f_readlink(INT32 args)
       error("readlink(): Out of memory\n");
     }
 
-    THREADS_ALLOW();
+    THREADS_ALLOW_UID();
     do {
       err = readlink(path, buf, buflen);
     } while ((err < 0) && (errno == EINTR));
-    THREADS_DISALLOW();
+    THREADS_DISALLOW_UID();
   } while (err >= buflen - 1);
 
   if (err < 0) {
@@ -250,11 +250,11 @@ void f_chmod(INT32 args)
   int err;
 
   get_all_args("chmod", args, "%s%i", &path, &mode);
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   do {
     err = chmod(path, mode);
   } while ((err < 0) && (errno == EINTR));
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
   if (err < 0) {
     report_error("chmod");
   }
@@ -270,11 +270,11 @@ void f_chown(INT32 args)
   int err;
 
   get_all_args("chown", args, "%s%i%i", &path, &uid, &gid);
-  THREADS_ALLOW();
+  THREADS_ALLOW_UID();
   do {
     err = chown(path, uid, gid);
   } while((err < 0) && (errno == EINTR));
-  THREADS_DISALLOW();
+  THREADS_DISALLOW_UID();
   if (err < 0) {
     report_error("chown");
   }
diff --git a/src/program.c b/src/program.c
index fbc0616411..b5921c041d 100644
--- a/src/program.c
+++ b/src/program.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: program.c,v 1.66 1998/03/18 20:22:31 per Exp $");
+RCSID("$Id: program.c,v 1.67 1998/03/26 14:30:58 grubba Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -837,6 +837,7 @@ struct program *end_first_pass(int finish)
 
   compilation_depth--;
   threads_disabled--;
+  co_signal(&threads_disabled_change);
   free_all_nodes();
   return prog;
 }
diff --git a/src/threads.c b/src/threads.c
index 8cfc49b688..71cfb189b3 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1,5 +1,5 @@
 #include "global.h"
-RCSID("$Id: threads.c,v 1.64 1998/03/26 05:48:24 per Exp $");
+RCSID("$Id: threads.c,v 1.65 1998/03/26 14:30:59 grubba Exp $");
 
 int num_threads = 1;
 int threads_disabled = 0;
@@ -16,6 +16,10 @@ int threads_disabled = 0;
 #include "gc.h"
 #include "main.h"
 
+int live_threads = 0;
+COND_T live_threads_change;
+COND_T threads_disabled_change;
+
 #ifdef __NT__
 
 #ifdef DEBUG
@@ -155,11 +159,18 @@ struct thread_starter
 void exit_threads_disable(struct object *o)
 {
   if(threads_disabled) threads_disabled--;
+  co_broadcast(&threads_disabled_change);
 }
 
 void init_threads_disable(struct object *o)
 {
   threads_disabled++;
+  while (live_threads) {
+    THREADS_FPRINTF((stderr,
+		     "_disable_threads(): Waiting for %d threads to finish\n",
+		     live_threads));
+    co_wait(&live_threads_change, &interpreter_lock);
+  }
 }
 
 /* Thread hashtable */
@@ -723,6 +734,8 @@ void th_init(void)
   mt_init( & interpreter_lock);
   mt_lock( & interpreter_lock);
   mt_init( & thread_table_lock);
+  co_init( & live_threads_change);
+  co_init( & threads_disabled_change);
   thread_table_init();
 #ifdef POSIX_THREADS
   pthread_attr_init(&pattr);
diff --git a/src/threads.h b/src/threads.h
index a4c6b961a9..ec647a7f5a 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -45,6 +45,7 @@
 
 
 extern int num_threads;
+extern int live_threads;
 struct object;
 extern struct object *thread_id;
 
@@ -221,6 +222,8 @@ int co_destroy(COND_T *c);
 
 extern MUTEX_T interpreter_lock;
 
+extern COND_T live_threads_change;		/* Used by _disable_threads */
+extern COND_T threads_disabled_change;		/* Used by _disable_threads */
 
 struct svalue;
 struct frame;
@@ -338,8 +341,9 @@ struct thread_state {
      struct thread_state *_tmp=(struct thread_state *)thread_id->storage; \
      if(num_threads > 1 && !threads_disabled) { \
        SWAP_OUT_THREAD(_tmp); \
-       THREADS_FPRINTF((stderr, "THREADS_ALLOW() %s:%d t:%08x\n", \
-			__FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \
+       THREADS_FPRINTF((stderr, "THREADS_ALLOW() %s:%d t:%08x (#%d)\n", \
+			__FILE__, __LINE__, \
+			(unsigned int)_tmp->thread_id, live_threads)); \
        mt_unlock(& interpreter_lock); \
      } else {} \
      HIDE_GLOBAL_VARIABLES()
@@ -348,12 +352,46 @@ struct thread_state {
      REVEAL_GLOBAL_VARIABLES(); \
      if(_tmp->swapped) { \
        mt_lock(& interpreter_lock); \
-       THREADS_FPRINTF((stderr, "THREADS_DISALLOW() %s:%d ... t:%08x\n", \
-			__FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \
+       THREADS_FPRINTF((stderr, "THREADS_DISALLOW() %s:%d... t:%08x (#%d)\n", \
+			__FILE__, __LINE__, \
+                        (unsigned int)_tmp->thread_id, live_threads)); \
+       while (threads_disabled) { \
+         THREADS_FPRINTF((stderr, "THREADS_DISALLOW(): Threads disabled\n")); \
+         co_wait(&live_threads_change, &interpreter_lock); \
+       } \
        SWAP_IN_THREAD(_tmp);\
      } \
    } while(0)
 
+#define THREADS_ALLOW_UID() do { \
+     struct thread_state *_tmp_uid=(struct thread_state *)thread_id->storage; \
+     if(num_threads > 1 && !threads_disabled) { \
+       SWAP_OUT_THREAD(_tmp_uid); \
+       live_threads++; \
+       THREADS_FPRINTF((stderr, "THREADS_ALLOW() %s:%d t:%08x (#%d)\n", \
+			__FILE__, __LINE__, \
+			(unsigned int)_tmp_uid->thread_id, live_threads)); \
+       mt_unlock(& interpreter_lock); \
+     } else {} \
+     HIDE_GLOBAL_VARIABLES()
+
+#define THREADS_DISALLOW_UID() \
+     REVEAL_GLOBAL_VARIABLES(); \
+     if(_tmp_uid->swapped) { \
+       mt_lock(& interpreter_lock); \
+       live_threads--; \
+       THREADS_FPRINTF((stderr, "THREADS_DISALLOW() %s:%d... t:%08x (#%d)\n", \
+			__FILE__, __LINE__, \
+                        (unsigned int)_tmp_uid->thread_id, live_threads)); \
+       while (threads_disabled) { \
+         THREADS_FPRINTF((stderr, "THREADS_DISALLOW(): Threads disabled\n")); \
+         co_signal(&live_threads_change); \
+         co_wait(&threads_disabled_change, &interpreter_lock); \
+       } \
+       SWAP_IN_THREAD(_tmp_uid);\
+     } \
+   } while(0)
+
 /* Prototypes begin here */
 struct thread_starter;
 void *new_thread_func(void * data);
-- 
GitLab