Index: tests/child-stopped-test.c
===================================================================
--- tests/child-stopped-test.c	(revision 0)
+++ tests/child-stopped-test.c	(revision 0)
@@ -0,0 +1,100 @@
+
+#include <assert.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <glib.h>
+
+
+guint
+child_watch_add (GPid            pid,
+		 GChildWatchFunc function,
+		 gpointer        data)
+{
+  GSource *source;
+  guint id;
+  
+  g_return_val_if_fail (function != NULL, 0);
+
+  source = g_child_watch_source_new (pid);
+  g_source_set_callback (source, (GSourceFunc) function, data, NULL);
+  g_child_watch_source_include_stops (source);
+  id = g_source_attach (source, NULL);
+  g_source_unref (source);
+
+  return id;
+}
+
+
+GMainLoop *main_loop;
+int callbacks = 0;
+int saved_status = 0;
+
+gboolean
+child_watch_callback (GPid pid, gint status, gpointer data)
+{
+  saved_status = status;
+  callbacks++;
+  g_main_loop_quit (main_loop);
+  return TRUE;
+}
+
+static gboolean
+quit_loop (gpointer data)
+{
+  g_main_loop_quit (main_loop);
+  return TRUE;
+}
+
+/* This test fails if run under "strace -f" because strace restarts
+   stopped processes. */
+
+int
+main (int argc, char *argv[])
+{
+  GMainContext *context = g_main_context_default ();
+  GPid pid = fork();
+  if (pid == 0)
+    {
+      kill (getpid (), SIGSTOP);
+      kill (getpid (), SIGTSTP);
+      _exit (123);
+    }
+  main_loop = g_main_loop_new (NULL, FALSE);
+  g_timeout_add (30000, quit_loop, main_loop);
+  child_watch_add (pid, child_watch_callback, 0);
+
+  g_main_loop_run (main_loop);
+  assert (callbacks == 1);
+  assert (WIFSTOPPED (saved_status));
+  assert (WSTOPSIG (saved_status) == SIGSTOP);
+
+  /* Running mainloop again should give no change. */
+  g_main_context_iteration (context, FALSE);
+  assert (callbacks == 1);
+
+  /* Check that we receive notification a second time through the same
+     handler. */
+  kill (pid, SIGCONT);
+  g_main_loop_run (main_loop);
+  assert (callbacks == 2);
+  assert (WIFSTOPPED (saved_status));
+  assert (WSTOPSIG (saved_status) == SIGTSTP);
+
+  /* Running mainloop again should give no change. */
+  g_main_context_iteration (context, FALSE);
+  assert (callbacks == 2);
+
+  /* The child process should exit this time after we restart it. */
+  kill (pid, SIGCONT);
+  g_main_loop_run (main_loop);
+  assert (callbacks == 3);
+  assert (WIFEXITED (saved_status));
+  assert (WEXITSTATUS (saved_status) == 123);
+
+  /* Running mainloop again should give no change. */
+  g_main_context_iteration (context, FALSE);
+  assert (callbacks == 3);
+
+  return 0;
+}
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 7675)
+++ tests/Makefile.am	(working copy)
@@ -100,6 +100,7 @@
 	bit-test				\
 	$(CXX_TEST)				\
 	checksum-test				\
+	child-stopped-test			\
 	child-test				\
 	completion-test				\
 	convert-test				\
@@ -164,6 +165,7 @@
 bit_test_LDADD = $(progs_ldadd)
 bookmarkfile_test_LDADD = $(progs_ldadd)
 checksum_test_LDADD = $(progs_ldadd)
+child_stopped_test_LDADD = $(thread_ldadd)
 child_test_LDADD = $(thread_ldadd)
 completion_test_LDADD = $(progs_ldadd)
 convert_test_LDADD = $(progs_ldadd)
Index: glib/gmain.c
===================================================================
--- glib/gmain.c	(revision 7675)
+++ glib/gmain.c	(working copy)
@@ -192,8 +192,9 @@
 #ifdef G_OS_WIN32
   GPollFD     poll;
 #else /* G_OS_WIN32 */
+  gboolean    include_stops;
   gint        count;
-  gboolean    child_exited;
+  gboolean    child_status_pending;
 #endif /* G_OS_WIN32 */
 };
 
@@ -3575,22 +3576,25 @@
 
   child_watch_source = (GChildWatchSource *) source;
 
-  if (child_watch_source->child_exited)
+  if (child_watch_source->child_status_pending)
     return TRUE;
 
   if (child_watch_source->count < count)
     {
       gint child_status;
+      int flags = 0;
+      if (child_watch_source->include_stops)
+	flags |= WUNTRACED;
 
-      if (waitpid (child_watch_source->pid, &child_status, WNOHANG) > 0)
+      if (waitpid (child_watch_source->pid, &child_status, WNOHANG | flags) > 0)
 	{
 	  child_watch_source->child_status = child_status;
-	  child_watch_source->child_exited = TRUE;
+	  child_watch_source->child_status_pending = TRUE;
 	}
       child_watch_source->count = count;
     }
 
-  return child_watch_source->child_exited;
+  return child_watch_source->child_status_pending;
 }
 
 static gboolean
@@ -3630,8 +3634,14 @@
 
   (child_watch_callback) (child_watch_source->pid, child_watch_source->child_status, user_data);
 
-  /* We never keep a child watch source around as the child is gone */
-  return FALSE;
+  if (WIFSTOPPED (child_watch_source->child_status))
+    {
+      child_watch_source->child_status_pending = FALSE;
+      return TRUE;
+    }
+  else
+    /* Don't keep a child watch source around because the child is gone */
+    return FALSE;
 }
 
 #ifndef G_OS_WIN32
@@ -3664,7 +3674,7 @@
 
   action.sa_handler = g_child_watch_signal_handler;
   sigemptyset (&action.sa_mask);
-  action.sa_flags = SA_NOCLDSTOP;
+  action.sa_flags = 0;
   sigaction (SIGCHLD, &action, NULL);
 }
 
@@ -3718,7 +3728,7 @@
  
   action.sa_handler = g_child_watch_signal_handler;
   sigemptyset (&action.sa_mask);
-  action.sa_flags = SA_RESTART | SA_NOCLDSTOP;
+  action.sa_flags = SA_RESTART;
   sigaction (SIGCHLD, &action, NULL);
 }
 
@@ -3891,7 +3901,14 @@
   return g_child_watch_add_full (G_PRIORITY_DEFAULT, pid, function, data, NULL);
 }
 
+void
+g_child_watch_source_include_stops (GSource *source)
+{
+  GChildWatchSource *child_watch_source = (GChildWatchSource *) source;
+  child_watch_source->include_stops = TRUE;
+}
 
+
 /* Idle functions */
 
 static gboolean 
Index: glib/gmain.h
===================================================================
--- glib/gmain.h	(revision 7675)
+++ glib/gmain.h	(working copy)
@@ -281,6 +281,7 @@
 guint    g_child_watch_add          (GPid            pid,
 				     GChildWatchFunc function,
 				     gpointer        data);
+void     g_child_watch_source_include_stops (GSource *source);
 guint    g_idle_add                 (GSourceFunc     function,
 				     gpointer        data);
 guint    g_idle_add_full            (gint            priority,
Index: glib/glib.symbols
===================================================================
--- glib/glib.symbols	(revision 7675)
+++ glib/glib.symbols	(working copy)
@@ -600,6 +600,7 @@
 #if IN_FILE(__G_MAIN_C__)
 g_child_watch_add
 g_child_watch_add_full
+g_child_watch_source_include_stops
 g_child_watch_source_new
 g_get_current_time
 g_main_context_acquire
