gsubprocess: Fix up communicate

We weren't closing the streams after we were done reading or writing,
which is kind of essential.  The easy way to fix this is to just use
g_output_stream_splice() to a GMemoryOutputStream rather than
hand-rolling it.  This results in a substantial reduction of code
complexity.

A second serious issue is that we were marking the task as complete when
the process exits, but that's racy - there could still be data to read
from stdout.  Fix this by just refcounting outstanding operations.

This code, not surprisingly, looks a lot like the "multi" test.

Next, because processes output binary data, I'd be forced to annotate
the char*/length pairs as (array) (element-type uint8).  But rather than
doing that, it's *far* simpler to just use GBytes.

We need a version of this that actually validates as UTF-8, that will be
in the next patch.
This commit is contained in:
Colin Walters
2013-10-15 00:12:22 +01:00
committed by Ryan Lortie
parent 5b48dc40cc
commit 0e1a3ee345
5 changed files with 198 additions and 344 deletions

View File

@@ -124,18 +124,14 @@ gint g_subprocess_get_term_sig (GSubprocess *s
GLIB_AVAILABLE_IN_2_40
gboolean g_subprocess_communicate (GSubprocess *subprocess,
const gchar *stdin_data,
gssize stdin_length,
GBytes *stdin_buf,
GCancellable *cancellable,
gchar **stdout_data,
gsize *stdout_length,
gchar **stderr_data,
gsize *stderr_length,
GBytes **stdout_buf,
GBytes **stderr_buf,
GError **error);
GLIB_AVAILABLE_IN_2_40
void g_subprocess_communicate_async (GSubprocess *subprocess,
const gchar *stdin_data,
gssize stdin_length,
GBytes *stdin_buf,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
@@ -143,30 +139,8 @@ void g_subprocess_communicate_async (GSubprocess *s
GLIB_AVAILABLE_IN_2_40
gboolean g_subprocess_communicate_finish (GSubprocess *subprocess,
GAsyncResult *result,
gchar **stdout_data,
gsize *stdout_length,
gchar **stderr_data,
gsize *stderr_length,
GError **error);
GLIB_AVAILABLE_IN_2_40
gboolean g_subprocess_communicate_bytes (GSubprocess *subprocess,
GBytes *stdin_bytes,
GCancellable *cancellable,
GBytes **stdout_bytes,
GBytes **stderr_bytes,
GError **error);
GLIB_AVAILABLE_IN_2_40
void g_subprocess_communicate_bytes_async (GSubprocess *subprocess,
GBytes *stdin_bytes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GLIB_AVAILABLE_IN_2_40
gboolean g_subprocess_communicate_bytes_finish (GSubprocess *subprocess,
GAsyncResult *result,
GBytes **stdout_bytes,
GBytes **stderr_bytes,
GBytes **stdout_buf,
GBytes **stderr_buf,
GError **error);
G_END_DECLS