X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgsubprocess.c;h=999d777e4f8d07c7b2b63cf405e1a364d1b349f7;hb=958da1e9dc82fbb91862501226b8928faf2f9558;hp=ca9b00607f2047e9e1ab7102ea72a1450a4d4274;hpb=1e5e3b64a8f3caa4c42a49b17b89dbbede892a90;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gsubprocess.c b/gio/gsubprocess.c index ca9b006..999d777 100644 --- a/gio/gsubprocess.c +++ b/gio/gsubprocess.c @@ -18,6 +18,7 @@ * SECTION:gsubprocess * @title: GSubprocess * @short_description: Child processes + * @include: gio/gio.h * @see_also: #GSubprocessLauncher * * #GSubprocess allows the creation of and interaction with child @@ -35,16 +36,15 @@ * comprehensive API for asynchronous I/O, such * g_output_stream_splice_async(). This makes GSubprocess * significantly more powerful and flexible than equivalent APIs in - * some other languages such as the subprocess.py + * some other languages such as the `subprocess.py` * included with Python. For example, using #GSubprocess one could * create two child processes, reading standard output from the first, * processing it, and writing to the input stream of the second, all * without blocking the main loop. * * A powerful g_subprocess_communicate() API is provided similar to the - * communicate() method of - * subprocess.py. This enables very easy interaction - * with a subprocess that has been opened with pipes. + * `communicate()` method of `subprocess.py`. This enables very easy + * interaction with a subprocess that has been opened with pipes. * * #GSubprocess defaults to tight control over the file descriptors open * in the child process, avoiding dangling-fd issues that are caused by @@ -71,8 +71,8 @@ * change of working directory, child setup functions, etc). * * A typical use of #GSubprocess will involve calling - * g_subprocess_new(), followed by g_subprocess_wait() or - * g_subprocess_wait_sync(). After the process exits, the status can be + * g_subprocess_new(), followed by g_subprocess_wait_async() or + * g_subprocess_wait(). After the process exits, the status can be * checked using functions such as g_subprocess_get_if_exited() (which * are similar to the familiar WIFEXITED-style POSIX macros). * @@ -108,6 +108,12 @@ #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#else +#define HAVE_O_CLOEXEC 1 +#endif + #define COMMUNICATE_READ_SIZE 4096 /* A GSubprocess can have two possible states: running and not. @@ -356,6 +362,10 @@ unix_open_file (const char *filename, g_free (display_name); /* fall through... */ } +#ifndef HAVE_O_CLOEXEC + else + fcntl (my_fd, F_SETFD, FD_CLOEXEC); +#endif return my_fd; } @@ -600,12 +610,15 @@ g_subprocess_finalize (GObject *object) g_clear_object (&self->stderr_pipe); g_strfreev (self->argv); + g_mutex_clear (&self->pending_waits_lock); + G_OBJECT_CLASS (g_subprocess_parent_class)->finalize (object); } static void g_subprocess_init (GSubprocess *self) { + g_mutex_init (&self->pending_waits_lock); } static void @@ -636,8 +649,8 @@ g_subprocess_class_init (GSubprocessClass *class) * g_subprocess_new: (skip) * @flags: flags that define the behaviour of the subprocess * @error: (allow-none): return location for an error, or %NULL - * @argv0: first commandline argument to pass to the subprocess, - * followed by more arguments, followed by %NULL + * @argv0: first commandline argument to pass to the subprocess + * @...: more commandline arguments, followed by %NULL * * Create a new process with the given flags and varargs argument * list. By default, matching the g_spawn_async() defaults, the @@ -673,6 +686,7 @@ g_subprocess_new (GSubprocessFlags flags, while ((arg = va_arg (ap, const gchar *))) g_ptr_array_add (args, (gchar *) arg); g_ptr_array_add (args, NULL); + va_end (ap); result = g_subprocess_newv ((const gchar * const *) args->pdata, flags, error); @@ -683,7 +697,7 @@ g_subprocess_new (GSubprocessFlags flags, /** * g_subprocess_newv: - * @argv: commandline arguments for the subprocess + * @argv: (array zero-terminated=1) (element-type utf8): commandline arguments for the subprocess * @flags: flags that define the behaviour of the subprocess * @error: (allow-none): return location for an error, or %NULL * @@ -710,6 +724,13 @@ g_subprocess_newv (const gchar * const *argv, NULL); } +/** + * g_subprocess_get_identifier: + * @subprocess: a #GSubprocess + * + * On UNIX, returns the process ID as a decimal string. + * On Windows, returns the result of GetProcessId() also as a string. + */ const gchar * g_subprocess_get_identifier (GSubprocess *subprocess) { @@ -731,7 +752,7 @@ g_subprocess_get_identifier (GSubprocess *subprocess) * The process must have been created with * %G_SUBPROCESS_FLAGS_STDIN_PIPE. * - * Returns: the stdout pipe + * Returns: (transfer none): the stdout pipe * * Since: 2.40 **/ @@ -754,7 +775,7 @@ g_subprocess_get_stdin_pipe (GSubprocess *subprocess) * The process must have been created with * %G_SUBPROCESS_FLAGS_STDOUT_PIPE. * - * Returns: the stdout pipe + * Returns: (transfer none): the stdout pipe * * Since: 2.40 **/ @@ -777,7 +798,7 @@ g_subprocess_get_stdout_pipe (GSubprocess *subprocess) * The process must have been created with * %G_SUBPROCESS_FLAGS_STDERR_PIPE. * - * Returns: the stderr pipe + * Returns: (transfer none): the stderr pipe * * Since: 2.40 **/ @@ -920,6 +941,9 @@ g_subprocess_sync_complete (GAsyncResult **result) * This function does not fail in the case of the subprocess having * abnormal termination. See g_subprocess_wait_check() for that. * + * Cancelling @cancellable doesn't kill the subprocess. Call + * g_subprocess_force_exit() if it is desirable. + * * Returns: %TRUE on success, %FALSE if @cancellable was cancelled * * Since: 2.40 @@ -1400,7 +1424,7 @@ g_subprocess_communicate_made_progress (GObject *source_object, source == state->stdout_buf || source == state->stderr_buf) { - if (!g_output_stream_splice_finish ((GOutputStream*)source, result, &error)) + if (g_output_stream_splice_finish ((GOutputStream*) source, result, &error) == -1) goto out; if (source == state->stdout_buf || @@ -1551,7 +1575,7 @@ g_subprocess_communicate_internal (GSubprocess *subprocess, /** * g_subprocess_communicate: * @subprocess: a #GSubprocess - * @stdin_buf: data to send to the stdin of the subprocess, or %NULL + * @stdin_buf: (allow-none): data to send to the stdin of the subprocess, or %NULL * @cancellable: a #GCancellable * @stdout_buf: (out): data read from the subprocess stdout * @stderr_buf: (out): data read from the subprocess stderr @@ -1560,7 +1584,7 @@ g_subprocess_communicate_internal (GSubprocess *subprocess, * Communicate with the subprocess until it terminates, and all input * and output has been completed. * - * If @stdin is given, the subprocess must have been created with + * If @stdin_buf is given, the subprocess must have been created with * %G_SUBPROCESS_FLAGS_STDIN_PIPE. The given data is fed to the * stdin of the subprocess and the pipe is closed (ie: EOF). * @@ -1632,8 +1656,8 @@ g_subprocess_communicate (GSubprocess *subprocess, /** * g_subprocess_communicate_async: * @subprocess: Self - * @stdin_buf: Input data - * @cancellable: Cancellable + * @stdin_buf: (allow-none): Input data, or %NULL + * @cancellable: (allow-none): Cancellable * @callback: Callback * @user_data: User data * @@ -1698,7 +1722,7 @@ g_subprocess_communicate_finish (GSubprocess *subprocess, /** * g_subprocess_communicate_utf8: * @subprocess: a #GSubprocess - * @stdin_buf: data to send to the stdin of the subprocess, or %NULL + * @stdin_buf: (allow-none): data to send to the stdin of the subprocess, or %NULL * @cancellable: a #GCancellable * @stdout_buf: (out): data read from the subprocess stdout * @stderr_buf: (out): data read from the subprocess stderr @@ -1718,13 +1742,16 @@ g_subprocess_communicate_utf8 (GSubprocess *subprocess, GAsyncResult *result = NULL; gboolean success; GBytes *stdin_bytes; + size_t stdin_buf_len = 0; g_return_val_if_fail (G_IS_SUBPROCESS (subprocess), FALSE); g_return_val_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE), FALSE); g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); - stdin_bytes = g_bytes_new (stdin_buf, strlen (stdin_buf)); + if (stdin_buf != NULL) + stdin_buf_len = strlen (stdin_buf); + stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len); g_subprocess_sync_setup (); g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable, @@ -1740,12 +1767,12 @@ g_subprocess_communicate_utf8 (GSubprocess *subprocess, /** * g_subprocess_communicate_utf8_async: * @subprocess: Self - * @stdin_buf: Input data + * @stdin_buf: (allow-none): Input data, or %NULL * @cancellable: Cancellable * @callback: Callback * @user_data: User data * - * Asynchronous version of g_subprocess_communicate_utf(). Complete + * Asynchronous version of g_subprocess_communicate_utf8(). Complete * invocation with g_subprocess_communicate_utf8_finish(). */ void @@ -1756,13 +1783,18 @@ g_subprocess_communicate_utf8_async (GSubprocess *subprocess, gpointer user_data) { GBytes *stdin_bytes; + size_t stdin_buf_len = 0; g_return_if_fail (G_IS_SUBPROCESS (subprocess)); g_return_if_fail (stdin_buf == NULL || (subprocess->flags & G_SUBPROCESS_FLAGS_STDIN_PIPE)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); - stdin_bytes = g_bytes_new (stdin_buf, strlen (stdin_buf)); + if (stdin_buf != NULL) + stdin_buf_len = strlen (stdin_buf); + stdin_bytes = g_bytes_new (stdin_buf, stdin_buf_len); + g_subprocess_communicate_internal (subprocess, TRUE, stdin_bytes, cancellable, callback, user_data); + g_bytes_unref (stdin_bytes); }