mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 22:46:15 +01:00
mainloop-test: Fix race conditions
* Wait for adder threads before deallocating crawler_array and context_array to avoid use after-free and data race. * Handle spurious wakeups around g_cond_wait. * Avoid starting recurser_idle without context. Fixes issue #1530.
This commit is contained in:
parent
d512c0fe43
commit
88f36a1d6f
@ -263,10 +263,10 @@ adder_response (GIOChannel *source,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static GThread *
|
||||||
create_adder_thread (void)
|
create_adder_thread (void)
|
||||||
{
|
{
|
||||||
GError *err = NULL;
|
GThread *thread;
|
||||||
TestData *test_data;
|
TestData *test_data;
|
||||||
|
|
||||||
GIOChannel *in_channels[2];
|
GIOChannel *in_channels[2];
|
||||||
@ -282,13 +282,7 @@ create_adder_thread (void)
|
|||||||
sub_channels[0] = in_channels[0];
|
sub_channels[0] = in_channels[0];
|
||||||
sub_channels[1] = out_channels[1];
|
sub_channels[1] = out_channels[1];
|
||||||
|
|
||||||
g_thread_create (adder_thread, sub_channels, FALSE, &err);
|
thread = g_thread_new ("adder", adder_thread, sub_channels);
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
g_warning ("Cannot create thread: %s", err->message);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
test_data = g_new (TestData, 1);
|
test_data = g_new (TestData, 1);
|
||||||
test_data->in = in_channels[1];
|
test_data->in = in_channels[1];
|
||||||
@ -299,6 +293,8 @@ create_adder_thread (void)
|
|||||||
adder_response, test_data);
|
adder_response, test_data);
|
||||||
|
|
||||||
do_add (test_data->in, test_data->current_val, INCREMENT);
|
do_add (test_data->in, test_data->current_val, INCREMENT);
|
||||||
|
|
||||||
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_crawler (void);
|
static void create_crawler (void);
|
||||||
@ -389,12 +385,15 @@ recurser_start (gpointer data)
|
|||||||
GSource *source;
|
GSource *source;
|
||||||
|
|
||||||
g_mutex_lock (&context_array_mutex);
|
g_mutex_lock (&context_array_mutex);
|
||||||
context = context_array->pdata[g_random_int_range (0, context_array->len)];
|
if (context_array->len > 0)
|
||||||
source = g_idle_source_new ();
|
{
|
||||||
g_source_set_name (source, "Recursing idle source");
|
context = context_array->pdata[g_random_int_range (0, context_array->len)];
|
||||||
g_source_set_callback (source, recurser_idle, context, NULL);
|
source = g_idle_source_new ();
|
||||||
g_source_attach (source, context);
|
g_source_set_name (source, "Recursing idle source");
|
||||||
g_source_unref (source);
|
g_source_set_callback (source, recurser_idle, context, NULL);
|
||||||
|
g_source_attach (source, context);
|
||||||
|
g_source_unref (source);
|
||||||
|
}
|
||||||
g_mutex_unlock (&context_array_mutex);
|
g_mutex_unlock (&context_array_mutex);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -405,6 +404,7 @@ main (int argc,
|
|||||||
char *argv[])
|
char *argv[])
|
||||||
{
|
{
|
||||||
gint i;
|
gint i;
|
||||||
|
GThread *threads[NTHREADS];
|
||||||
|
|
||||||
context_array = g_ptr_array_new ();
|
context_array = g_ptr_array_new ();
|
||||||
|
|
||||||
@ -413,13 +413,13 @@ main (int argc,
|
|||||||
main_loop = g_main_loop_new (NULL, FALSE);
|
main_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
|
||||||
for (i = 0; i < NTHREADS; i++)
|
for (i = 0; i < NTHREADS; i++)
|
||||||
create_adder_thread ();
|
threads[i] = create_adder_thread ();
|
||||||
|
|
||||||
/* Wait for all threads to start
|
/* Wait for all threads to start
|
||||||
*/
|
*/
|
||||||
g_mutex_lock (&context_array_mutex);
|
g_mutex_lock (&context_array_mutex);
|
||||||
|
|
||||||
if (context_array->len < NTHREADS)
|
while (context_array->len < NTHREADS)
|
||||||
g_cond_wait (&context_array_cond, &context_array_mutex);
|
g_cond_wait (&context_array_cond, &context_array_mutex);
|
||||||
|
|
||||||
g_mutex_unlock (&context_array_mutex);
|
g_mutex_unlock (&context_array_mutex);
|
||||||
@ -432,6 +432,9 @@ main (int argc,
|
|||||||
g_main_loop_run (main_loop);
|
g_main_loop_run (main_loop);
|
||||||
g_main_loop_unref (main_loop);
|
g_main_loop_unref (main_loop);
|
||||||
|
|
||||||
|
for (i = 0; i < NTHREADS; i++)
|
||||||
|
g_thread_join (threads[i]);
|
||||||
|
|
||||||
g_ptr_array_unref (crawler_array);
|
g_ptr_array_unref (crawler_array);
|
||||||
g_ptr_array_unref (context_array);
|
g_ptr_array_unref (context_array);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user