diff --git a/src/signal_handler.c b/src/signal_handler.c
index ff0c38280546652e90c403fcd4b66329099b23a1..65c009548b1b76b4b45e4dba2117ac128a161498 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: signal_handler.c,v 1.322 2006/10/31 00:26:21 nilsson Exp $
+|| $Id: signal_handler.c,v 1.323 2006/12/27 16:28:34 grubba Exp $
 */
 
 #include "global.h"
@@ -1129,6 +1129,7 @@ struct pid_status
   int flags;
   int state;
   int result;
+  struct svalue callback;
 #endif
 };
 
@@ -1144,6 +1145,8 @@ static void init_pid_status(struct object *o)
   THIS->flags=0;
   THIS->state=PROCESS_UNKNOWN;
   THIS->result=-1;
+  THIS->callback.type = T_INT;
+  THIS->callback.u.integer = 0;
 #endif
 }
 
@@ -1165,6 +1168,21 @@ static void exit_pid_status(struct object *o)
 }
 
 #ifdef USE_PID_MAPPING
+static void call_pid_status_callback(struct callback *cb, void *pid, void *arg)
+{
+  struct object *o = pid;
+  struct pid_status *p;
+  remove_callback(cb);
+  if (!o) return;
+  if(!(p=(struct pid_status *)get_storage(o, pid_status_program))) {
+    free_object(o);
+    return;
+  }
+  /* Steal the reference from o. */
+  push_object(o);
+  safe_apply_svalue(&p->callback, 1, 1);
+  pop_stack();
+}
 static void report_child(int pid,
 			 WAITSTATUSTYPE status,
 			 const char *from)
@@ -1184,12 +1202,20 @@ static void report_child(int pid,
     key.u.integer=pid;
     if((s=low_mapping_lookup(pid_mapping, &key)))
     {
+      struct pid_status *p = NULL;
+      int call_callback = 0;
       if(s->type == T_OBJECT)
       {
-	struct pid_status *p;
-	if((p=(struct pid_status *)get_storage(s->u.object,
+	struct object *o;
+	if((p=(struct pid_status *)get_storage((o = s->u.object),
 					       pid_status_program)))
 	{
+	  if (!SAFE_IS_ZERO(&p->callback)) {
+	    /* Call the callback from a proper pike thread... */
+	    add_ref(o);
+	    add_to_callback(&evaluator_callbacks, call_pid_status_callback,
+			    o, NULL);
+	  }
 	  if(WIFSTOPPED(status)) {
 	    p->sig = WSTOPSIG(status);
 	    p->state = PROCESS_STOPPED;
@@ -1228,6 +1254,10 @@ static void report_child(int pid,
        * when we want to keep the entry. This is currently
        * achieved with the return above.
        *	/grubba 2003-02-28
+       *
+       * Note that this also invalidates s (and p unless we have added
+       * extra references to the object).
+       *	/grubba 2006-12-27
        */
       map_delete(pid_mapping, &key);
     }else{
@@ -2409,6 +2439,7 @@ int fd_cleanup_cb(void *data, int fd)
 #else
   set_close_on_exec(fd, 1);
 #endif
+  return 0;
 }
 #endif /* HAVE_FDWALK */
 
@@ -2441,6 +2472,9 @@ int fd_cleanup_cb(void *data, int fd)
  *!
  *! @mapping
  *!
+ *! @member function(Process.Process:void) "callback"
+ *!  Function called when the created process changes state.
+ *!
  *! @member string "cwd"
  *!  Execute the command in another directory than the current
  *!  directory of this process. Please note that if the command is
@@ -2581,9 +2615,14 @@ int fd_cleanup_cb(void *data, int fd)
  *!   noticeably slower using a string instead of an integer; if maximum
  *!   performance is an issue, please use integers.
  *!
- *!   The modifiers @expr{"fds"@}, @expr{"uid"@}, @expr{"gid"@},
+ *! @note
+ *!   The modifiers @expr{"callback"@}, @expr{"fds"@},
+ *!   @expr{"uid"@}, @expr{"gid"@},
  *!   @expr{"nice"@}, @expr{"noinitgroups"@}, @expr{"setgroups"@},
  *!   @expr{"keep_signals"@} and @expr{"rlimit"@} only exist on unix.
+ *!
+ *! @note
+ *!   Support for @expr{"callback"@} was added in Pike 7.7.
  */
 
 /*! @endclass */
@@ -2995,6 +3034,9 @@ void f_create_process(INT32 args)
 
     if(optional)
     {
+      if ((tmp = simple_mapping_string_lookup(optional, "callback"))) {
+	assign_svalue(&(THIS->callback), tmp);
+      }
       if((tmp = simple_mapping_string_lookup(optional, "priority")) &&
          tmp->type == T_STRING)
         priority = tmp->u.string->str;
@@ -4775,8 +4817,13 @@ void init_signals(void)
   }
 #endif
 
-  start_new_program();
+  START_NEW_PROGRAM_ID(PROCESS);
   ADD_STORAGE(struct pid_status);
+#ifndef __NT__
+  PIKE_MAP_VARIABLE("__callback", OFFSETOF(pid_status, callback),
+		    tFunc(tObjIs_PROCESS,tVoid), T_MIXED,
+		    ID_STATIC|ID_PRIVATE);
+#endif /* !__NT__ */
   set_init_callback(init_pid_status);
   set_exit_callback(exit_pid_status);
   /* function(string:int) */