diff options
author | Philip Withnall <withnall@endlessm.com> | 2019-10-25 16:36:45 +0100 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2019-10-25 16:36:45 +0100 |
commit | a7242d4a5e5e5875699bcff2749beac19864943b (patch) | |
tree | f6cd57663e0103da0d0880266108c310ddb096a7 | |
parent | 5e17a98d1947b4090e661ae114f37653d9126dc3 (diff) | |
download | glib-a7242d4a5e5e5875699bcff2749beac19864943b.tar.gz |
gspawn: Port to g_poll() from select()
This removes the limitation of select() that only FDs with values lower
than FD_SETSIZE can be used. Previously, if the out/err pipe FDs had
high values (which could happen if a large process, like Firefox, was
spawning subprocesses while having a lot of FDs open), GLib would abort
due to an assertion failure in libc.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
Fixes: #954
-rw-r--r-- | glib/gspawn.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/glib/gspawn.c b/glib/gspawn.c index bcbaec78f..85813ef00 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -372,7 +372,6 @@ g_spawn_sync (const gchar *working_directory, gint outpipe = -1; gint errpipe = -1; GPid pid; - fd_set fds; gint ret; GString *outstr = NULL; GString *errstr = NULL; @@ -435,16 +434,16 @@ g_spawn_sync (const gchar *working_directory, (outpipe >= 0 || errpipe >= 0)) { - FD_ZERO (&fds); - if (outpipe >= 0) - FD_SET (outpipe, &fds); - if (errpipe >= 0) - FD_SET (errpipe, &fds); - - ret = select (MAX (outpipe, errpipe) + 1, - &fds, - NULL, NULL, - NULL /* no timeout */); + /* Any negative FD in the array is ignored, so we can use a fixed length. + * We can use UNIX FDs here without worrying about Windows HANDLEs because + * the Windows implementation is entirely in gspawn-win32.c. */ + GPollFD fds[] = + { + { outpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 }, + { errpipe, G_IO_IN | G_IO_HUP | G_IO_ERR, 0 }, + }; + + ret = g_poll (fds, G_N_ELEMENTS (fds), -1 /* no timeout */); if (ret < 0) { @@ -458,13 +457,13 @@ g_spawn_sync (const gchar *working_directory, g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_READ, - _("Unexpected error in select() reading data from a child process (%s)"), + _("Unexpected error in reading data from a child process (%s)"), g_strerror (errsv)); break; } - if (outpipe >= 0 && FD_ISSET (outpipe, &fds)) + if (outpipe >= 0 && fds[0].revents != 0) { switch (read_data (outstr, outpipe, error)) { @@ -483,7 +482,7 @@ g_spawn_sync (const gchar *working_directory, break; } - if (errpipe >= 0 && FD_ISSET (errpipe, &fds)) + if (errpipe >= 0 && fds[1].revents != 0) { switch (read_data (errstr, errpipe, error)) { |