From 5f06241c99ad43ceb52a4ce6ea5e1ea9429c9db7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Sun, 11 Apr 1999 19:24:19 -0700
Subject: [PATCH] atexit() and weak arrays implemented

Rev: src/array.c:1.46
Rev: src/array.h:1.17
Rev: src/builtin_functions.c:1.166
Rev: src/encode.c:1.31
Rev: src/main.c:1.70
Rev: src/object.c:1.70
Rev: src/signal_handler.c:1.123
Rev: src/signal_handler.h:1.7
---
 src/array.c             |  44 +++++++++++++-
 src/array.h             |   8 ++-
 src/builtin_functions.c |  30 ++++++----
 src/encode.c            |   9 ++-
 src/main.c              |   7 ++-
 src/object.c            |  19 +-----
 src/signal_handler.c    | 125 +++++++++++++++++++++++++---------------
 src/signal_handler.h    |  15 ++++-
 8 files changed, 167 insertions(+), 90 deletions(-)

diff --git a/src/array.c b/src/array.c
index 57a3289ec4..ea2ae488ed 100644
--- a/src/array.c
+++ b/src/array.c
@@ -20,7 +20,7 @@
 #include "main.h"
 #include "security.h"
 
-RCSID("$Id: array.c,v 1.45 1999/03/19 11:40:12 hubbe Exp $");
+RCSID("$Id: array.c,v 1.46 1999/04/12 02:24:10 hubbe Exp $");
 
 struct array empty_array=
 {
@@ -1685,7 +1685,7 @@ void check_all_arrays(void)
 
 void gc_mark_array_as_referenced(struct array *a)
 {
-  if(gc_mark(a))
+  if(gc_mark(a) && !(a->flags & ARRAY_WEAK_FLAG))
     if(a->type_field & BIT_COMPLEX)
       gc_mark_svalues(ITEM(a), a->size);
 }
@@ -1751,7 +1751,45 @@ void gc_free_all_unreferenced_arrays(void)
 
       free_array(a);
       a=next;
-    }else{
+    }
+    else if(a->flags & ARRAY_WEAK_FLAG)
+    {
+      int e;
+      add_ref(a);
+
+      if(a->flags & ARRAY_WEAK_SHRINK)
+      {
+	int d=0;
+	for(e=0;e<a->size;e++)
+	{
+	  if(a->item[e].type <= MAX_COMPLEX && gc_do_free(a->item[e].u.refs))
+	    free_svalue(a->item+e);
+	  else
+	    a->item[d++]=a->item[e];
+	}
+	a->size=e;
+      }else{
+	for(e=0;e<a->size;e++)
+	{
+	  if(a->item[e].type <= MAX_COMPLEX && gc_do_free(a->item[e].u.refs))
+	  {
+	    free_svalue(a->item+e);
+	    a->item[e].type=T_INT;
+	    a->item[e].u.integer=0;
+	    a->item[e].subtype=NUMBER_DESTRUCTED;
+	    a->type_field |= BIT_INT;
+	  }
+	}
+      }
+	  
+      if(!(next=a->next))
+	fatal("Null pointer in array list.\n");
+
+      free_array(a);
+      a=next;
+    }
+    else
+    {
       a=a->next;
     }
   } while (a != & empty_array);
diff --git a/src/array.h b/src/array.h
index da0674db11..2b09ba8342 100644
--- a/src/array.h
+++ b/src/array.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: array.h,v 1.16 1999/03/06 05:55:39 hubbe Exp $
+ * $Id: array.h,v 1.17 1999/04/12 02:24:11 hubbe Exp $
  */
 #ifndef ARRAY_H
 #define ARRAY_H
@@ -31,8 +31,10 @@ struct array
   struct svalue item[1];
 };
 
-#define ARRAY_CYCLIC 1
-#define ARRAY_LVALUE 2
+#define ARRAY_WEAK_FLAG 1
+#define ARRAY_CYCLIC 2
+#define ARRAY_LVALUE 4
+#define ARRAY_WEAK_SHRINK 8
 
 extern struct array empty_array;
 
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 7fbfb62966..eae21cd73a 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.165 1999/04/03 06:10:04 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.166 1999/04/12 02:24:12 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -1872,21 +1872,26 @@ void f_mkmapping(INT32 args)
   push_mapping(m);
 }
 
+#define SETFLAG(FLAGS,FLAG,ONOFF) \
+  FLAGS = (FLAGS & ~FLAG) | ( ONOFF ? FLAG : 0 )
 void f_set_weak_flag(INT32 args)
 {
   int ret;
-  struct mapping *m;
-  get_all_args("set_weak_flag",args,"%m%i",&m,&ret);
-  if(ret)
+  struct svalue *s;
+  get_all_args("set_weak_flag",args,"%*%i",&s,&ret);
+
+  switch(s->type)
   {
-    ret=m->flags & MAPPING_FLAG_WEAK;
-    m->flags|=MAPPING_FLAG_WEAK;
-  }else{
-    ret=m->flags & MAPPING_FLAG_WEAK;
-    m->flags&=~MAPPING_FLAG_WEAK;
+    case T_ARRAY:
+      SETFLAG(s->u.array->flags,ARRAY_WEAK_FLAG,ret);
+      break;
+    case T_MAPPING:
+      SETFLAG(s->u.mapping->flags,MAPPING_FLAG_WEAK,ret);
+      break;
+    default:
+      SIMPLE_BAD_ARG_ERROR("set_weak_flag",1,"array|mapping");
   }
-  pop_n_elems(args);
-  push_int(!!ret);
+  pop_n_elems(args-1);
 }
 
 
@@ -3936,6 +3941,7 @@ void f_map_array(INT32 args)
   push_array(ret);
 }
 
+
 void init_builtin_efuns(void)
 {
   ADD_EFUN("gethrtime", f_gethrtime,tFunc(tOr(tInt,tVoid),tInt), OPT_EXTERNAL_DEPEND);
@@ -4053,7 +4059,7 @@ void init_builtin_efuns(void)
   ADD_EFUN("mkmapping",f_mkmapping,tFunc(tArr(tSetvar(1,tMix)) tArr(tSetvar(2,tMix)),tMap(tVar(1),tVar(2))),OPT_TRY_OPTIMIZE);
   
 /* function(mapping,int:int) */
-  ADD_EFUN("set_weak_flag",f_set_weak_flag,tFunc(tMapping tInt,tInt),OPT_SIDE_EFFECT);
+  ADD_EFUN("set_weak_flag",f_set_weak_flag,tFunc(tSetvar(1,tMix) tInt,tVar(1)),OPT_SIDE_EFFECT);
   
 /* function(void|object:object) */
   ADD_EFUN("next_object",f_next_object,tFunc(tOr(tVoid,tObj),tObj),OPT_EXTERNAL_DEPEND);
diff --git a/src/encode.c b/src/encode.c
index 2cee4877ad..b20bce0cac 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -24,7 +24,7 @@
 #include "stuff.h"
 #include "version.h"
 
-RCSID("$Id: encode.c,v 1.30 1999/03/07 20:19:43 grubba Exp $");
+RCSID("$Id: encode.c,v 1.31 1999/04/12 02:24:14 hubbe Exp $");
 
 #ifdef _AIX
 #include <net/nh.h>
@@ -886,7 +886,12 @@ static void decode_value2(struct decode_data *data)
 	  
 	case 1:
 	  decode_value2(data);
-	  f_arrow(2);
+	  if(sp[-2].type==T_INT)
+	  {
+	    pop_stack();
+	  }else{
+	    f_arrow(2);
+	  }
 	  break;
 	  
 	default:
diff --git a/src/main.c b/src/main.c
index e671588249..a7031447aa 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: main.c,v 1.69 1999/04/08 23:54:29 hubbe Exp $");
+RCSID("$Id: main.c,v 1.70 1999/04/12 02:24:15 hubbe Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -505,7 +505,9 @@ void low_init_main(void)
 
 void exit_main(void)
 {
+#ifdef DO_PIKE_CLEANUP
   cleanup_objects();
+#endif
 }
 
 void init_main(void)
@@ -514,6 +516,7 @@ void init_main(void)
 
 void low_exit_main(void)
 {
+#ifdef DO_PIKE_CLEANUP
   void cleanup_added_efuns(void);
   void cleanup_pike_types(void);
   void cleanup_program(void);
@@ -611,7 +614,7 @@ void low_exit_main(void)
 #endif
 
   really_clean_up_interpret();
-#ifdef DO_PIKE_CLEANUP
+
   cleanup_callbacks();
   free_all_callable_blocks();
   exit_destroy_called_mark_hash();
diff --git a/src/object.c b/src/object.c
index 7f3f7cf32a..158ab3eca4 100644
--- a/src/object.c
+++ b/src/object.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: object.c,v 1.69 1999/04/08 22:27:08 hubbe Exp $");
+RCSID("$Id: object.c,v 1.70 1999/04/12 02:24:16 hubbe Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -977,34 +977,19 @@ int object_equal_p(struct object *a, struct object *b, struct processing *p)
 void cleanup_objects(void)
 {
   struct object *o, *next;
-  for(o=first_object;o;o=next)
-  {
-    add_ref(o);
-    call_destroy(o,1);
-    next=o->next;
-    free_object(o);
-  }
 
   for(o=first_object;o;o=next)
   {
     add_ref(o);
-    low_destruct(o,
-#ifdef DO_PIKE_CLEANUP
-		 1
-#else
-		 0
-#endif
-      );
+    low_destruct(o,1);
     next=o->next;
     free_object(o);
   }
-#ifdef DO_PIKE_CLEANUP
   free_object(master_object);
   master_object=0;
   free_program(master_program);
   master_program=0;
   destruct_objects_to_destruct();
-#endif
 }
 
 struct array *object_indices(struct object *o)
diff --git a/src/signal_handler.c b/src/signal_handler.c
index 23635aa226..3dfb49df27 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.c
@@ -22,9 +22,10 @@
 #include "operators.h"
 #include "builtin_functions.h"
 #include "security.h"
+#include "main.h"
 #include <signal.h>
 
-RCSID("$Id: signal_handler.c,v 1.122 1999/04/09 04:48:43 hubbe Exp $");
+RCSID("$Id: signal_handler.c,v 1.123 1999/04/12 02:24:17 hubbe Exp $");
 
 #ifdef HAVE_PASSWD_H
 # include <passwd.h>
@@ -119,8 +120,8 @@ extern int fd_from_object(struct object *o);
 static int set_priority( int pid, char *to );
 
 
-
 static struct svalue signal_callbacks[MAX_SIGNALS];
+static void (*default_signals[MAX_SIGNALS])(INT32);
 static unsigned char sigbuf[SIGNAL_BUFFER];
 static int firstsig, lastsig;
 static struct callback *signal_evaluator_callback =0;
@@ -452,20 +453,8 @@ void check_signals(struct callback *foo, void *bar, void *gazonk)
 
       if(IS_ZERO(signal_callbacks + sigbuf[lastsig]))
       {
-	switch(sigbuf[lastsig])
-	{
-#ifdef SIGINT
-	  case SIGINT:
-#endif
-#ifdef SIGHUP
-	  case SIGHUP:
-#endif
-#ifdef SIGQUIT
-	  case SIGQUIT:
-#endif
-	    push_int(1);
-	    f_exit(1);
-	}
+	if(default_signals[sigbuf[lastsig]])
+	  default_signals[sigbuf[lastsig]](sigbuf[lastsig]);
       }else{
 	push_int(sigbuf[lastsig]);
 	apply_svalue(signal_callbacks + sigbuf[lastsig], 1);
@@ -551,35 +540,29 @@ static void f_signal(int args)
     switch(signum)
     {
 #ifdef USE_SIGCHLD
-    case SIGCHLD:
-      func=receive_sigchild;
-      break;
+      case SIGCHLD:
+	func=receive_sigchild;
+	break;
 #endif
-
+	
 #ifdef SIGPIPE
-    case SIGPIPE:
-      func=(sigfunctype) SIG_IGN;
-      break;
-#endif
-
-#ifdef SIGHUP
-      case SIGHUP:
-#endif
-#ifdef SIGINT
-      case SIGINT:
-#endif
-#ifdef SIGQUIT
-      case SIGQUIT:
+      case SIGPIPE:
+	func=(sigfunctype) SIG_IGN;
+	break;
 #endif
-	func=receive_signal;
+	
+      default:
+	if(default_signals[signum])
+	  func=receive_signal;
+	else
+	  func=(sigfunctype) SIG_DFL;
 	break;
-
-    default:
-      func=(sigfunctype) SIG_DFL;
     }
   } else {
     if(IS_ZERO(sp+1-args))
     {
+      /* Fixme: this can disrupt sigchild and other important signal handling
+       */
       func=(sigfunctype) SIG_IGN;
     }else{
       func=receive_signal;
@@ -594,6 +577,15 @@ static void f_signal(int args)
   pop_n_elems(args);
 }
 
+void set_default_signal_handler(int signum, void (*func)(INT32))
+{
+  int is_on=!!IS_ZERO(signal_callbacks+signum);
+  int want_on=!!func;
+  default_signals[signum]=func;
+  if(is_on!=want_on)
+    my_signal(signum, want_on ? receive_signal : (sigfunctype) SIG_DFL);
+}
+
 static void f_signum(int args)
 {
   int i;
@@ -2734,6 +2726,52 @@ static RETSIGTYPE fatal_signal(int signum)
 }
 #endif
 
+
+
+static struct array *atexit_functions;
+
+static void run_atexit_functions(struct callback *cb, void *arg,void *arg2)
+{
+  if(atexit_functions)
+  {
+    push_array(atexit_functions);
+    atexit_functions=0;
+    f_reverse(1);
+    f_call_function(1);
+    pop_stack();
+  }
+}
+
+static void do_signal_exit(INT32 sig)
+{
+  push_int(sig);
+  f_exit(1);
+}
+
+void f_atexit(INT32 args)
+{
+  if(!atexit_functions)
+  {
+#ifdef SIGHUP
+    set_default_signal_handler(SIGHUP, do_signal_exit);
+#endif
+#ifdef SIGINT
+    set_default_signal_handler(SIGINT, do_signal_exit);
+#endif
+#ifdef SIGQUIT
+    set_default_signal_handler(SIGQUIT, do_signal_exit);
+#endif
+    add_exit_callback(run_atexit_functions,0,0);
+    atexit_functions=low_allocate_array(0,1);
+  }
+
+  f_aggregate(args);
+  atexit_functions=append_array(atexit_functions,sp-1);
+  atexit_functions->flags |= ARRAY_WEAK_FLAG | ARRAY_WEAK_SHRINK;
+  pop_stack();
+}
+
+
 void init_signals(void)
 {
   int e;
@@ -2769,17 +2807,6 @@ void init_signals(void)
   my_signal(SIGFPE, SIG_IGN);
 #endif
 
-#ifdef SIGINT
-  my_signal(SIGINT, receive_signal);
-#endif
-
-#ifdef SIGHUP
-  my_signal(SIGHUP, receive_signal);
-#endif
-
-#ifdef SIGQUIT
-  my_signal(SIGQUIT, receive_signal);
-#endif
 
   for(e=0;e<MAX_SIGNALS;e++)
     signal_callbacks[e].type=T_INT;
@@ -2854,6 +2881,8 @@ void init_signals(void)
   
 /* function(int:int) */
   ADD_EFUN("ualarm",f_ualarm,tFunc(tInt,tInt),OPT_SIDE_EFFECT);
+
+  ADD_EFUN("atexit",f_atexit,tFuncV( ,tMix,tVoid),OPT_SIDE_EFFECT);
 #endif
 }
 
diff --git a/src/signal_handler.h b/src/signal_handler.h
index 5dff97b625..e42f56ec20 100644
--- a/src/signal_handler.h
+++ b/src/signal_handler.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: signal_handler.h,v 1.6 1998/03/28 14:59:32 grubba Exp $
+ * $Id: signal_handler.h,v 1.7 1999/04/12 02:24:19 hubbe Exp $
  */
 #ifndef SIGNAL_H
 #define SIGNAL_H
@@ -13,13 +13,22 @@
 typedef RETSIGTYPE (*sigfunctype) (int);
 
 /* Prototypes begin here */
-struct wait_data;
 struct sigdesc;
 void my_signal(int sig, sigfunctype fun);
+void check_signals(struct callback *foo, void *bar, void *gazonk);
+void set_default_signal_handler(int signum, void (*func)(INT32));
+void process_started(pid_t pid);
+void process_done(pid_t pid);
+struct wait_data;
 struct pid_status;
+struct perishables;
+struct plimit;
+struct perishables;
+void f_set_priority( INT32 args );
 void f_create_process(INT32 args);
 void f_fork(INT32 args);
-void check_signals(struct callback *foo, void *bar, void *gazonk);
+void f_kill(INT32 args);
+void f_atexit(INT32 args);
 void init_signals(void);
 void exit_signals(void);
 /* Prototypes end here */
-- 
GitLab