mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-05 18:40:58 +01:00
gmain/tests: add unit test for g_child_watch_add() reaping processes without notifying
The test currently tests broken behavior. It will be fixed next.
This commit is contained in:
parent
54d1ebfc37
commit
d1e558f492
@ -372,6 +372,105 @@ test_get_passwd_entry_nonexistent (void)
|
|||||||
g_clear_error (&local_error);
|
g_clear_error (&local_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_child_wait_watch_cb (GPid pid,
|
||||||
|
gint wait_status,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
gboolean *p_got_callback = user_data;
|
||||||
|
|
||||||
|
g_assert_nonnull (p_got_callback);
|
||||||
|
g_assert_false (*p_got_callback);
|
||||||
|
*p_got_callback = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_child_wait (void)
|
||||||
|
{
|
||||||
|
gboolean r;
|
||||||
|
GPid pid;
|
||||||
|
guint id;
|
||||||
|
pid_t pid2;
|
||||||
|
int wstatus;
|
||||||
|
gboolean got_callback = FALSE;
|
||||||
|
gboolean iterate_maincontext = g_test_rand_bit ();
|
||||||
|
char **argv;
|
||||||
|
int errsv;
|
||||||
|
|
||||||
|
/* - We spawn a trivial child process that exits after a short time.
|
||||||
|
* - We schedule a g_child_watch_add()
|
||||||
|
* - we may iterate the GMainContext a bit. Randomly we either get the
|
||||||
|
* child-watcher callback or not.
|
||||||
|
* - if we didn't get the callback, we g_source_remove() the child watcher.
|
||||||
|
*
|
||||||
|
* Afterwards, if the callback didn't fire, we check that we are able to waitpid()
|
||||||
|
* on the process ourselves. Of course, if the child watcher notified, the waitpid()
|
||||||
|
* will fail with ECHILD.
|
||||||
|
*/
|
||||||
|
|
||||||
|
argv = g_test_rand_bit () ? ((char *[]){ "/bin/sleep", "0.05", NULL }) : ((char *[]){ "/bin/true", NULL });
|
||||||
|
|
||||||
|
r = g_spawn_async (NULL,
|
||||||
|
argv,
|
||||||
|
NULL,
|
||||||
|
G_SPAWN_DO_NOT_REAP_CHILD,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&pid,
|
||||||
|
NULL);
|
||||||
|
if (!r)
|
||||||
|
{
|
||||||
|
/* Some odd system without /bin/sleep? Skip the test. */
|
||||||
|
g_test_skip ("failure to spawn test process in test_child_wait()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_cmpint (pid, >=, 1);
|
||||||
|
|
||||||
|
if (g_test_rand_bit ())
|
||||||
|
g_usleep (g_test_rand_int_range (0, (G_USEC_PER_SEC / 10)));
|
||||||
|
|
||||||
|
id = g_child_watch_add (pid, _child_wait_watch_cb, &got_callback);
|
||||||
|
|
||||||
|
if (g_test_rand_bit ())
|
||||||
|
g_usleep (g_test_rand_int_range (0, (G_USEC_PER_SEC / 10)));
|
||||||
|
|
||||||
|
if (iterate_maincontext)
|
||||||
|
{
|
||||||
|
gint64 start_usec = g_get_monotonic_time ();
|
||||||
|
gint64 end_usec = start_usec + g_test_rand_int_range (0, (G_USEC_PER_SEC / 10));
|
||||||
|
|
||||||
|
while (!got_callback && g_get_monotonic_time () < end_usec)
|
||||||
|
g_main_context_iteration (NULL, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!got_callback)
|
||||||
|
g_source_remove (id);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
pid2 = waitpid (pid, &wstatus, 0);
|
||||||
|
errsv = errno;
|
||||||
|
if (got_callback)
|
||||||
|
{
|
||||||
|
g_assert_true (iterate_maincontext);
|
||||||
|
g_assert_cmpint (errsv, ==, ECHILD);
|
||||||
|
g_assert_cmpint (pid2, <, 0);
|
||||||
|
}
|
||||||
|
else if (errsv == ECHILD)
|
||||||
|
{
|
||||||
|
/* FIXME: This is a bug. We didn't get the callback from the child
|
||||||
|
* watcher, but still the child is already reaped. */
|
||||||
|
g_assert_cmpint (pid2, <, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_cmpint (errsv, ==, 0);
|
||||||
|
g_assert_cmpint (pid2, ==, pid);
|
||||||
|
g_assert_true (WIFEXITED (wstatus));
|
||||||
|
g_assert_cmpint (WEXITSTATUS (wstatus), ==, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
@ -390,6 +489,7 @@ main (int argc,
|
|||||||
g_test_add_func ("/glib-unix/callback_after_signal", test_callback_after_signal);
|
g_test_add_func ("/glib-unix/callback_after_signal", test_callback_after_signal);
|
||||||
g_test_add_func ("/glib-unix/get-passwd-entry/root", test_get_passwd_entry_root);
|
g_test_add_func ("/glib-unix/get-passwd-entry/root", test_get_passwd_entry_root);
|
||||||
g_test_add_func ("/glib-unix/get-passwd-entry/nonexistent", test_get_passwd_entry_nonexistent);
|
g_test_add_func ("/glib-unix/get-passwd-entry/nonexistent", test_get_passwd_entry_nonexistent);
|
||||||
|
g_test_add_func ("/glib-unix/child-wait", test_child_wait);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user