Race condition in `g_subprocess_communicate()` with `G_SUBPROCESS_FLAGS_STDIN_PIPE`
When using g_subprocess_communicate()
with a stdin
buffer, a race condition may occur resulting in SIGPIPE
.
This seems to be triggered by a process terminating early, such passing an invalid command-line option. It also seems much easier to reproduce with a larger stdin
buffer size.
Reproducer tested in GLib 2.80.0:
#include <gio/gio.h>
#define BUF_SIZE (1024)
int
main (int argc,
char *argv[])
{
g_autoptr (GSubprocess) proc = NULL;
g_autoptr (GBytes) stdin_bytes = NULL;
g_autoptr (GBytes) stdout_bytes = NULL;
g_autoptr (GBytes) stderr_bytes = NULL;
char data[BUF_SIZE] = { 0, };
proc = g_subprocess_new (G_SUBPROCESS_FLAGS_STDIN_PIPE |
G_SUBPROCESS_FLAGS_STDOUT_PIPE |
G_SUBPROCESS_FLAGS_STDERR_PIPE,
NULL,
"cat", "--not-a-real-option", NULL);
stdin_bytes = g_bytes_new (data, BUF_SIZE);
g_subprocess_communicate (proc,
stdin_bytes,
NULL,
&stdout_bytes,
&stderr_bytes,
NULL);
return EXIT_SUCCESS;
}
GDB backtrace:
#0 0x00007ffff7b5886d in __GI___libc_write (fd=4, buf=0x414a50, nbytes=1024)
at ../sysdeps/unix/sysv/linux/write.c:26
#1 __GI___libc_write (fd=4, buf=buf@entry=0x414a50, nbytes=nbytes@entry=1024)
at ../sysdeps/unix/sysv/linux/write.c:24
#2 0x00007ffff7eb3e92 in g_unix_output_stream_write
(stream=0x412130 [GUnixOutputStream], buffer=0x414a50, count=1024, cancellable=0x0, error=0x7fffffffd770)
at ../gio/gunixoutputstream.c:363
#3 0x00007ffff7e75563 in write_async_pollable (stream=stream@entry=0x412130, task=task@entry=0x41c0c0 [GTask])
at ../gio/goutputstream.c:2428
#4 0x00007ffff7e756b9 in g_output_stream_real_write_async
(stream=0x412130 [GUnixOutputStream], buffer=0x414a50, count=1024, io_priority=<optimized out>, cancellable=<optimized out>, callback=0x7ffff7e74890 <real_splice_async_write_cb>, user_data=0x414990) at ../gio/goutputstream.c:2471
#5 0x00007ffff7e74b9c in real_splice_async_read_cb
(source=<optimized out>, res=<optimized out>, user_data=0x414990) at ../gio/goutputstream.c:2825
#6 0x00007ffff7e5dd57 in async_ready_callback_wrapper
(source_object=0x414860 [GMemoryInputStream], res=0x416a60, user_data=0x414990) at ../gio/ginputstream.c:565
#7 0x00007ffff7e909dc in g_task_return_now (task=0x416a60 [GTask]) at ../gio/gtask.c:1361
#8 0x00007ffff7e90a15 in complete_in_idle_cb (task=task@entry=0x416a60) at ../gio/gtask.c:1375
#9 0x00007ffff7c9cdad in g_idle_dispatch
(source=0x416b20, callback=0x7ffff7e90a00 <complete_in_idle_cb>, user_data=0x416a60) at ../glib/gmain.c:6150
#10 0x00007ffff7c9668c in g_main_dispatch (context=0x412a20) at ../glib/gmain.c:3344
#11 g_main_context_dispatch_unlocked (context=0x412a20) at ../glib/gmain.c:4152
#12 0x00007ffff7cf7788 in g_main_context_iterate_unlocked.isra.0
(context=context@entry=0x412a20, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>)
at ../glib/gmain.c:4217
#13 0x00007ffff7c97b03 in g_main_context_iteration (context=context@entry=0x412a20, may_block=may_block@entry=1)
at ../glib/gmain.c:4282
#14 0x00007ffff7e9661d in g_subprocess_sync_complete (result=0x7fffffffda80) at ../gio/gsubprocess.c:833
#15 g_subprocess_communicate
(subprocess=0x4110e0 [GSubprocess], stdin_buf=0x40fde0, cancellable=<optimized out>, stdout_buf=0x7fffffffdee8, stderr_buf=0x7fffffffdee0, error=0x0) at ../gio/gsubprocess.c:1580
#16 0x000000000040129b in main (argc=1, argv=0x7fffffffe038) at gsubfail.c:22
ThreadSanitizer error:
==================
WARNING: ThreadSanitizer: data race (pid=251928)
Write of size 8 at 0x720800000020 by thread T2:
#0 free <null> (libtsan.so.2+0x57aa0) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_free_sized <null> (libglib-2.0.so.0+0x5d494) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
Previous write of size 8 at 0x720800000020 by main thread:
#0 malloc <null> (libtsan.so.2+0x551e6) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_malloc <null> (libglib-2.0.so.0+0x62f89) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Thread T2 'pool-spawner' (tid=251933, running) created by main thread at:
#0 pthread_create <null> (libtsan.so.2+0x5a2d6) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_thread_new_internal <null> (libglib-2.0.so.0+0x8d76f) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
SUMMARY: ThreadSanitizer: data race (/lib64/libtsan.so.2+0x57aa0) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13) in free
==================
==================
WARNING: ThreadSanitizer: data race (pid=251928)
Write of size 8 at 0x72b0000000a0 by thread T3:
#0 close <null> (libtsan.so.2+0x54eaf) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_unix_input_stream_close <null> (libgio-2.0.so.0+0xce8d6) (BuildId: f37f1488e5713c456d81b7dc5a24d57b27268f6e)
Previous read of size 8 at 0x72b0000000a0 by main thread:
#0 read <null> (libtsan.so.2+0x5d744) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_unix_input_stream_read <null> (libgio-2.0.so.0+0xceca1) (BuildId: f37f1488e5713c456d81b7dc5a24d57b27268f6e)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Location is file descriptor 5 created by main thread at:
#0 pipe2 <null> (libtsan.so.2+0x57f1e) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_unix_open_pipe_internal.lto_priv.0.lto_priv.0 <null> (libglib-2.0.so.0+0x2070b) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Thread T3 'pool' (tid=251934, running) created by thread T2 at:
#0 pthread_create <null> (libtsan.so.2+0x5a2d6) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_thread_new_internal <null> (libglib-2.0.so.0+0x8d76f) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
SUMMARY: ThreadSanitizer: data race (/lib64/libtsan.so.2+0x54eaf) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13) in close
==================
==================
WARNING: ThreadSanitizer: data race (pid=251928)
Write of size 8 at 0x720400000af0 by thread T3:
#0 free <null> (libtsan.so.2+0x57aa0) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_free <null> (libglib-2.0.so.0+0x5d274) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
Previous write of size 8 at 0x720400000af0 by main thread:
#0 realloc <null> (libtsan.so.2+0x56fcd) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_realloc <null> (libglib-2.0.so.0+0x6402a) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Thread T3 'pool' (tid=251934, running) created by thread T2 at:
#0 pthread_create <null> (libtsan.so.2+0x5a2d6) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_thread_new_internal <null> (libglib-2.0.so.0+0x8d76f) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
SUMMARY: ThreadSanitizer: data race (/lib64/libtsan.so.2+0x57aa0) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13) in free
==================
==================
WARNING: ThreadSanitizer: data race (pid=251928)
Write of size 8 at 0x721400001810 by thread T3:
#0 free <null> (libtsan.so.2+0x57aa0) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_free <null> (libglib-2.0.so.0+0x5d274) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
Previous write of size 8 at 0x721400001810 by main thread:
#0 calloc <null> (libtsan.so.2+0x5532e) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_malloc0 <null> (libglib-2.0.so.0+0x63f71) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Thread T3 'pool' (tid=251934, running) created by thread T2 at:
#0 pthread_create <null> (libtsan.so.2+0x5a2d6) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_thread_new_internal <null> (libglib-2.0.so.0+0x8d76f) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
SUMMARY: ThreadSanitizer: data race (/lib64/libtsan.so.2+0x57aa0) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13) in free
==================
==================
WARNING: ThreadSanitizer: data race (pid=251928)
Write of size 8 at 0x72b000000080 by thread T3:
#0 close <null> (libtsan.so.2+0x54eaf) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_unix_output_stream_close <null> (libgio-2.0.so.0+0xce996) (BuildId: f37f1488e5713c456d81b7dc5a24d57b27268f6e)
Previous read of size 8 at 0x72b000000080 by main thread:
#0 write <null> (libtsan.so.2+0x5e083) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_unix_output_stream_write <null> (libgio-2.0.so.0+0xcee91) (BuildId: f37f1488e5713c456d81b7dc5a24d57b27268f6e)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Location is file descriptor 4 created by main thread at:
#0 pipe2 <null> (libtsan.so.2+0x57f1e) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_unix_open_pipe_internal.lto_priv.0.lto_priv.0 <null> (libglib-2.0.so.0+0x2070b) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
#2 __libc_start_call_main <null> (libc.so.6+0x2a087) (BuildId: 341d2be28035b1c2546e062799b0e8598dd1d726)
Thread T3 'pool' (tid=251934, running) created by thread T2 at:
#0 pthread_create <null> (libtsan.so.2+0x5a2d6) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13)
#1 g_thread_new_internal <null> (libglib-2.0.so.0+0x8d76f) (BuildId: 4eb9c94a71baf67c3bf333ea421ec28636a08f6b)
SUMMARY: ThreadSanitizer: data race (/lib64/libtsan.so.2+0x54eaf) (BuildId: 138c6fb498d699a761599d83ea34a40b3d5f0d13) in close
==================
ThreadSanitizer: reported 5 warnings
Edited by Andy Holmes