1/* GLIB - Library of useful routines for C programming 2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the 16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 * Boston, MA 02111-1307, USA. 18 */ 19 20/* 21 * Modified by the GLib Team and others 1997-2000. See the AUTHORS 22 * file for a list of people on the GLib Team. See the ChangeLog 23 * files for a list of changes. These files are distributed with 24 * GLib at ftp://ftp.gtk.org/pub/gtk/. 25 */ 26 27#include "config.h" 28 29#include <sys/types.h> 30#ifdef HAVE_UNISTD_H 31#include <unistd.h> 32#endif 33#include <stdlib.h> 34 35#include <glib.h> 36 37#ifdef G_OS_WIN32 38#include <windows.h> 39#endif 40 41#ifdef G_OS_WIN32 42#define GPID_FORMAT "%p" 43#else 44#define GPID_FORMAT "%d" 45#endif 46 47GMainLoop *main_loop; 48gint alive; 49 50#ifdef G_OS_WIN32 51char *argv0; 52#endif 53 54GPid 55get_a_child (gint ttl) 56{ 57 GPid pid; 58 59#ifdef G_OS_WIN32 60 STARTUPINFO si; 61 PROCESS_INFORMATION pi; 62 gchar *cmdline; 63 64 memset (&si, 0, sizeof (si)); 65 si.cb = sizeof (&si); 66 memset (&pi, 0, sizeof (pi)); 67 68 cmdline = g_strdup_printf( "child-test -c%d", ttl); 69 70 if (!CreateProcess (argv0, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 71 g_error ("CreateProcess failed: %s\n", g_win32_error_message (GetLastError ())); 72 73 g_free(cmdline); 74 75 CloseHandle (pi.hThread); 76 pid = pi.hProcess; 77 78 return pid; 79#else 80 pid = fork (); 81 if (pid < 0) 82 exit (1); 83 84 if (pid > 0) 85 return pid; 86 87 sleep (ttl); 88 _exit (0); 89#endif /* G_OS_WIN32 */ 90} 91 92gboolean 93child_watch_callback (GPid pid, gint status, gpointer data) 94{ 95#ifdef VERBOSE 96 gint ttl = GPOINTER_TO_INT (data); 97 98 g_print ("child " GPID_FORMAT " (ttl %d) exited, status %d\n", pid, ttl, status); 99#endif 100 101 g_spawn_close_pid (pid); 102 103 if (--alive == 0) 104 g_main_loop_quit (main_loop); 105 106 return TRUE; 107} 108 109static gboolean 110quit_loop (gpointer data) 111{ 112 GMainLoop *main_loop = data; 113 114 g_main_loop_quit (main_loop); 115 116 return TRUE; 117} 118 119#ifdef TEST_THREAD 120static gpointer 121test_thread (gpointer data) 122{ 123 GMainLoop *new_main_loop; 124 GSource *source; 125 GPid pid; 126 gint ttl = GPOINTER_TO_INT (data); 127 128 new_main_loop = g_main_loop_new (NULL, FALSE); 129 130 pid = get_a_child (ttl); 131 source = g_child_watch_source_new (pid); 132 g_source_set_callback (source, (GSourceFunc) child_watch_callback, data, NULL); 133 g_source_attach (source, g_main_loop_get_context (new_main_loop)); 134 g_source_unref (source); 135 136#ifdef VERBOSE 137 g_print ("whee! created pid: " GPID_FORMAT " (ttl %d)\n", pid, ttl); 138#endif 139 140 g_main_loop_run (new_main_loop); 141 142 return NULL; 143} 144#endif 145 146int 147main (int argc, char *argv[]) 148{ 149#ifndef TEST_THREAD 150 GPid pid; 151#endif 152#ifdef G_OS_WIN32 153 argv0 = argv[0]; 154 if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'c') 155 { 156 int ttl = atoi (argv[1] + 2); 157 Sleep (ttl * 1000); 158 /* Exit on purpose with STILL_ACTIVE (which isn't a very common 159 * exit status) to verify that g_child_watch_check() in gmain.c 160 * doesn't believe a child still to be active if it happens to 161 * exit with that status. 162 */ 163 exit (STILL_ACTIVE); 164 } 165#endif 166 /* Only run the test, if threads are enabled and a default thread 167 * implementation is available. 168 */ 169#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE) 170#ifdef TEST_THREAD 171 g_thread_init (NULL); 172#endif 173 main_loop = g_main_loop_new (NULL, FALSE); 174 175#ifdef G_OS_WIN32 176 system ("ipconfig /all"); 177#else 178 system ("/bin/true"); 179#endif 180 181 alive = 2; 182 g_timeout_add (30000, quit_loop, main_loop); 183 184#ifdef TEST_THREAD 185 g_thread_create (test_thread, GINT_TO_POINTER (10), FALSE, NULL); 186 g_thread_create (test_thread, GINT_TO_POINTER (20), FALSE, NULL); 187#else 188 pid = get_a_child (10); 189 g_child_watch_add (pid, (GChildWatchFunc) child_watch_callback, 190 GINT_TO_POINTER (10)); 191 pid = get_a_child (20); 192 g_child_watch_add (pid, (GChildWatchFunc) child_watch_callback, 193 GINT_TO_POINTER (20)); 194#endif 195 196 g_main_loop_run (main_loop); 197 198 if (alive > 0) 199 { 200 g_warning ("%d children still alive\n", alive); 201 return 1; 202 } 203 204#endif 205 return 0; 206} 207