void WorkQueue::dispatchOnTermination(WebKit::PlatformProcessIdentifier process, const Function<void()>& function) { GRefPtr<GSource> dispatchSource = adoptGRef(g_child_watch_source_new(process)); ASSERT(dispatchSource); dispatchOnSource(dispatchSource.get(), function, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnTermination)); }
static gchar * gnuindent (GrindBackendGNUIndent *self, GeanyDocument *doc, const gchar *input, GError **error) { GPid pid; int input_fd; int output_fd; int error_fd; gchar *output = NULL; gchar **argv; argv = build_args (self, doc); if (g_spawn_async_with_pipes (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, &input_fd, &output_fd, &error_fd, error)) { GSource *source; GMainContext *ctx = g_main_context_new (); BlockData data; data.error = NULL; data.loop = g_main_loop_new (ctx, FALSE); data.output_str = g_string_new (NULL); data.error_str = g_string_new (NULL); source = g_child_watch_source_new (pid); g_source_set_callback (source, (GSourceFunc)child_watch_handler, &data, NULL); g_source_attach (source, ctx); g_source_unref (source); /* output */ add_watch_fd (output_fd, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, ctx, (GIOFunc)output_ready_handler, &data); /* error */ add_watch_fd (error_fd, G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, ctx, (GIOFunc)error_ready_handler, &data); if (write_input (input_fd, input, &data.error)) { g_main_loop_run (data.loop); } if (! data.error) { output = g_string_free (data.output_str, FALSE); } else { g_string_free (data.output_str, TRUE); g_propagate_error (error, data.error); } g_string_free (data.error_str, TRUE); g_main_loop_unref (data.loop); g_main_context_unref (ctx); } g_strfreev (argv); return output; }
void WorkQueue::scheduleWorkOnTermination(WebKit::PlatformProcessIdentifier process, PassOwnPtr<WorkItem> item) { GRefPtr<GSource> dispatchSource = adoptGRef(g_child_watch_source_new(process)); ASSERT(dispatchSource); scheduleWorkOnSource(dispatchSource.get(), item, reinterpret_cast<GSourceFunc>(&WorkQueue::EventSource::performWorkOnTermination)); }
/** * g_child_watch_add will bind the source to the "main" main context, * g_main_context_get_default(), which is not what we want */ static int g_child_watch_add_tothread(GPid pid, GChildWatchFunc function, gpointer data) { GSource *source; guint id; g_return_val_if_fail(function != NULL, 0); g_return_val_if_fail(pid > 0, 0); source = g_child_watch_source_new(pid); g_source_set_callback(source, (GSourceFunc) function, data, NULL); id = g_source_attach(source, g_main_context_get_thread_default()); g_source_unref(source); return id; }
static gboolean PowerOpsRunScript(PowerOpState *state, gchar *script) { gchar *argv[2]; GSource *watch; GError *err = NULL; argv[0] = g_locale_from_utf8(script, -1, NULL, NULL, &err); if (err != NULL) { g_debug("Conversion error: %s\n", err->message); g_clear_error(&err); /* * If we could not convert to current locate let's hope that * what we have is a useable script name and use it directly. */ argv[0] = g_strdup(script); } argv[1] = NULL; g_message("Executing script: '%s'\n", script); if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, &state->pid, &err)) { g_warning("Error starting script: %s\n", err->message); g_clear_error(&err); g_free(argv[0]); return FALSE; } /* Setup a watch for when the child is done. */ watch = g_child_watch_source_new(state->pid); VMTOOLSAPP_ATTACH_SOURCE(state->ctx, watch, PowerOpsScriptCallback, state, NULL); g_source_unref(watch); g_free(argv[0]); return TRUE; }
void SpiceController::WaitForPid(GPid pid) { GMainContext *context; GSource *source; context = g_main_context_new(); m_child_watch_mainloop = g_main_loop_new(context, FALSE); source = g_child_watch_source_new(pid); g_source_set_callback(source, (GSourceFunc)ChildExited, this, NULL); g_source_attach(source, context); g_main_loop_run(m_child_watch_mainloop); g_main_loop_unref(m_child_watch_mainloop); g_main_context_unref(context); g_spawn_close_pid(pid); if (pid == m_pid_controller) m_pid_controller = 0; }
static guint watch_child_full (GCutEventLoop *loop, gint priority, GPid pid, GChildWatchFunc function, gpointer data, GDestroyNotify notify) { GCutGLibEventLoopPrivate *priv; guint tag; GSource *source; priv = GCUT_GLIB_EVENT_LOOP_GET_PRIVATE(loop); source = g_child_watch_source_new(pid); if (priority != G_PRIORITY_DEFAULT) g_source_set_priority(source, priority); g_source_set_callback(source, (GSourceFunc)function, data, notify); tag = g_source_attach(source, g_main_loop_get_context(priv->loop)); g_source_unref(source); return tag; }
static gpointer test_thread (gpointer data) { GMainLoop *new_main_loop; GSource *source; GPid pid; gint ttl = GPOINTER_TO_INT (data); new_main_loop = g_main_loop_new (NULL, FALSE); pid = get_a_child (ttl); source = g_child_watch_source_new (pid); g_source_set_callback (source, (GSourceFunc) child_watch_callback, data, NULL); g_source_attach (source, g_main_loop_get_context (new_main_loop)); g_source_unref (source); #ifdef VERBOSE g_print ("whee! created pid: " GPID_FORMAT " (ttl %d)\n", pid, ttl); #endif g_main_loop_run (new_main_loop); return NULL; }
static verto_mod_ev * glib_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) { verto_mod_ev *evpriv = NULL; verto_ev_type type = verto_get_type(ev); *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_PERSIST; *flags |= verto_get_flags(ev) & VERTO_EV_FLAG_IO_CLOSE_FD; switch (type) { case VERTO_EV_TYPE_IO: evpriv = g_source_new(&funcs, sizeof(GIOSource)); if (evpriv) { ((GIOSource*) evpriv)->fd.fd = verto_get_fd(ev); ((GIOSource*) evpriv)->autoclose = *flags & VERTO_EV_FLAG_IO_CLOSE_FD; g_source_add_poll(evpriv, &((GIOSource*) evpriv)->fd); } break; case VERTO_EV_TYPE_TIMEOUT: evpriv = g_timeout_source_new(verto_get_interval(ev)); break; case VERTO_EV_TYPE_IDLE: evpriv = g_idle_source_new(); break; case VERTO_EV_TYPE_CHILD: evpriv = g_child_watch_source_new(verto_get_proc(ev)); break; case VERTO_EV_TYPE_SIGNAL: /* While glib has signal support in >=2.29, it does not support many common signals (like USR*). Therefore, signal support is disabled until they support them (should be soonish) */ #if GLIB_MAJOR_VERSION >= 999 #if GLIB_MINOR_VERSION >= 29 #ifdef G_OS_UNIX /* Not supported on Windows */ evpriv = g_unix_signal_source_new(verto_get_signal(ev)); break; #endif #endif /* GLIB_MINOR_VERSION >= 29 */ #endif /* GLIB_MAJOR_VERSION >= 2 */ default: return NULL; /* Not supported */ } if (!evpriv) goto error; if (type == VERTO_EV_TYPE_IO) g_source_set_callback(evpriv, (GSourceFunc) glib_callback_io, (void *) ev, NULL); else if (type == VERTO_EV_TYPE_CHILD) g_source_set_callback(evpriv, (GSourceFunc) glib_callback_child, (void *) ev, NULL); else g_source_set_callback(evpriv, glib_callback, (void *) ev, NULL); glib_ctx_set_flags(ctx, ev, evpriv); g_source_set_can_recurse(evpriv, FALSE); if (g_source_attach(evpriv, ctx->context) == 0) goto error; return evpriv; error: if (evpriv) { g_source_destroy(evpriv); g_source_unref(evpriv); } return NULL; }
static gboolean nm_openssh_start (NMVPNPlugin *plugin, NMSettingVPN *s_vpn, GError **error) { NMOpensshPluginPrivate *priv = NM_OPENSSH_PLUGIN_GET_PRIVATE(plugin); sshtun_handle_t handle; const char *tun_mode; char *tun_owner = NULL, *host = NULL, *user = NULL, *public_key = NULL, *private_key = NULL, *config_script = NULL; const char *val; int ret; gboolean retval = TRUE; GIOChannel *event_channel; GSource *child_watch, *event_watch; val = nm_setting_vpn_get_user_name (s_vpn); if (!val) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "%s", "Can't get username."); retval = FALSE; goto out; } tun_owner = g_strdup (val); val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_TUN_USE_TAP); tun_mode = val && !strcmp (val, "yes") ? "ethernet" : "pointopoint"; val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_USER); user = val ? g_strdup (val) : g_strdup (tun_owner); val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_HOST); if (!val) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "%s", "Host is missing."); retval = FALSE; goto out; } host = g_strdup (val); val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_PUBLIC_KEY); if (!val) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "%s", "SSH public key is missing."); retval = FALSE; goto out; } public_key = g_strdup (val); val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_PRIVATE_KEY); if (!val) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "%s", "SSH private key is missing."); retval = FALSE; goto out; } private_key = g_strdup (val); val = nm_setting_vpn_get_data_item (s_vpn, NM_OPENSSH_KEY_CONFIG_SCRIPT); if (!val) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "%s", "IP config script is missing."); retval = FALSE; goto out; } config_script = g_strdup (val); ret = sshtun_new (&handle); if (ret < 0) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_GENERAL, "%s", "Could not allocate memory for an sshtun process."); retval = FALSE; goto out; } ret = sshtun_set_params (handle, SSHTUN_PARAM_TUN_MODE, tun_mode, SSHTUN_PARAM_TUN_OWNER, tun_owner, SSHTUN_PARAM_USER, user, SSHTUN_PARAM_HOST, host, SSHTUN_PARAM_SERVICE, "ssh", SSHTUN_PARAM_PUBLIC_KEY, public_key, SSHTUN_PARAM_PRIVATE_KEY, private_key, SSHTUN_PARAM_CONFIG_SCRIPT, config_script, 0); if (ret < 0) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "%s", "Could not set parameters for an sshtun process."); retval = FALSE; goto out; } ret = sshtun_start (handle); if (ret < 0) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "%s", "Could not start an sshtun process."); retval = FALSE; goto out; } priv->handle = handle; val = nm_setting_vpn_get_secret (s_vpn, NM_OPENSSH_KEY_PASSWORD); priv->password = val ? g_strdup (val) : NULL; /* Watch the status change of the sshtun child process. */ child_watch = g_child_watch_source_new (sshtun_pid (priv->handle)); g_source_set_callback (child_watch, (GSourceFunc) child_watch_cb, plugin, NULL); g_source_attach (child_watch, NULL); g_source_unref (child_watch); /* Watch the normal event from the sshtun child process. */ event_channel = g_io_channel_unix_new (sshtun_event_fd (priv->handle)); event_watch = g_io_create_watch (event_channel, G_IO_IN); g_source_set_callback (event_watch, (GSourceFunc) event_watch_cb, plugin, NULL); g_source_attach (event_watch, NULL); g_source_unref (event_watch); g_io_channel_unref (event_channel); out: g_free (tun_owner); g_free (host); g_free (user); g_free (public_key); g_free (private_key); g_free (config_script); return retval; }
/* called when we're done running the command line */ static void udisks_spawned_job_release_resources (UlSpawnedJob *self) { /* Nuke the child, if necessary */ if (self->child_watch_source != NULL) { g_source_destroy (self->child_watch_source); self->child_watch_source = NULL; } if (self->child_pid != 0) { GSource *source; g_debug ("ugh, need to kill %d", (gint) self->child_pid); kill (self->child_pid, SIGTERM); /* OK, we need to reap for the child ourselves - we don't want * to use waitpid() because that might block the calling * thread (the child might handle SIGTERM and use several * seconds for cleanup/rollback). * * So we use GChildWatch instead. * * Note that we might be called from the finalizer so avoid * taking references to ourselves. We do need to pass the * GSource so we can nuke it once handled. */ source = g_child_watch_source_new (self->child_pid); g_source_set_callback (source, (GSourceFunc) child_watch_from_release_cb, source, (GDestroyNotify) g_source_destroy); g_source_attach (source, self->main_context); g_source_unref (source); self->child_pid = 0; } if (self->child_stdout != NULL) { g_string_free (self->child_stdout, TRUE); self->child_stdout = NULL; } if (self->child_stderr != NULL) { g_string_free (self->child_stderr, TRUE); self->child_stderr = NULL; } if (self->child_stdin_channel != NULL) { g_io_channel_unref (self->child_stdin_channel); self->child_stdin_channel = NULL; } if (self->child_stdout_channel != NULL) { g_io_channel_unref (self->child_stdout_channel); self->child_stdout_channel = NULL; } if (self->child_stderr_channel != NULL) { g_io_channel_unref (self->child_stderr_channel); self->child_stderr_channel = NULL; } if (self->child_stdin_source != NULL) { g_source_destroy (self->child_stdin_source); self->child_stdin_source = NULL; } if (self->child_stdout_source != NULL) { g_source_destroy (self->child_stdout_source); self->child_stdout_source = NULL; } if (self->child_stderr_source != NULL) { g_source_destroy (self->child_stderr_source); self->child_stderr_source = NULL; } if (self->child_stdin_fd != -1) { g_warn_if_fail (close (self->child_stdin_fd) == 0); self->child_stdin_fd = -1; } if (self->child_stdout_fd != -1) { g_warn_if_fail (close (self->child_stdout_fd) == 0); self->child_stdout_fd = -1; } if (self->child_stderr_fd != -1) { g_warn_if_fail (close (self->child_stderr_fd) == 0); self->child_stderr_fd = -1; } if (self->cancellable_handler_id > 0) { g_cancellable_disconnect (ul_job_get_cancellable (UL_JOB (self)), self->cancellable_handler_id); self->cancellable_handler_id = 0; } }
void gvfs_udisks2_utils_spawn (guint timeout_seconds, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, const gchar *command_line_format, ...) { va_list var_args; SpawnData *data; GError *error; gint child_argc; gchar **child_argv = NULL; data = g_slice_new0 (SpawnData); data->simple = g_simple_async_result_new (NULL, callback, user_data, gvfs_udisks2_utils_spawn); data->main_context = g_main_context_get_thread_default (); if (data->main_context != NULL) g_main_context_ref (data->main_context); data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL; va_start (var_args, command_line_format); data->command_line = g_strdup_vprintf (command_line_format, var_args); va_end (var_args); data->child_stdout = g_string_new (NULL); data->child_stderr = g_string_new (NULL); data->child_stdout_fd = -1; data->child_stderr_fd = -1; /* the life-cycle of SpawnData is tied to its GSimpleAsyncResult */ g_simple_async_result_set_op_res_gpointer (data->simple, data, (GDestroyNotify) spawn_data_free); error = NULL; if (data->cancellable != NULL) { /* could already be cancelled */ error = NULL; if (g_cancellable_set_error_if_cancelled (data->cancellable, &error)) { g_simple_async_result_take_error (data->simple, error); g_simple_async_result_complete_in_idle (data->simple); g_object_unref (data->simple); goto out; } data->cancellable_handler_id = g_cancellable_connect (data->cancellable, G_CALLBACK (on_cancelled), data, NULL); } error = NULL; if (!g_shell_parse_argv (data->command_line, &child_argc, &child_argv, &error)) { g_prefix_error (&error, "Error parsing command-line `%s': ", data->command_line); g_simple_async_result_take_error (data->simple, error); g_simple_async_result_complete_in_idle (data->simple); g_object_unref (data->simple); goto out; } error = NULL; if (!g_spawn_async_with_pipes (NULL, /* working directory */ child_argv, NULL, /* envp */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, /* child_setup */ NULL, /* child_setup's user_data */ &(data->child_pid), NULL, /* gint *stdin_fd */ &(data->child_stdout_fd), &(data->child_stderr_fd), &error)) { g_prefix_error (&error, "Error spawning command-line `%s': ", data->command_line); g_simple_async_result_take_error (data->simple, error); g_simple_async_result_complete_in_idle (data->simple); g_object_unref (data->simple); goto out; } if (timeout_seconds > 0) { data->timeout_source = g_timeout_source_new_seconds (timeout_seconds); g_source_set_priority (data->timeout_source, G_PRIORITY_DEFAULT); g_source_set_callback (data->timeout_source, timeout_cb, data, NULL); g_source_attach (data->timeout_source, data->main_context); g_source_unref (data->timeout_source); } data->child_watch_source = g_child_watch_source_new (data->child_pid); g_source_set_callback (data->child_watch_source, (GSourceFunc) child_watch_cb, data, NULL); g_source_attach (data->child_watch_source, data->main_context); g_source_unref (data->child_watch_source); data->child_stdout_channel = g_io_channel_unix_new (data->child_stdout_fd); g_io_channel_set_flags (data->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL); data->child_stdout_source = g_io_create_watch (data->child_stdout_channel, G_IO_IN); g_source_set_callback (data->child_stdout_source, (GSourceFunc) read_child_stdout, data, NULL); g_source_attach (data->child_stdout_source, data->main_context); g_source_unref (data->child_stdout_source); data->child_stderr_channel = g_io_channel_unix_new (data->child_stderr_fd); g_io_channel_set_flags (data->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL); data->child_stderr_source = g_io_create_watch (data->child_stderr_channel, G_IO_IN); g_source_set_callback (data->child_stderr_source, (GSourceFunc) read_child_stderr, data, NULL); g_source_attach (data->child_stderr_source, data->main_context); g_source_unref (data->child_stderr_source); out: g_strfreev (child_argv); }
static void cockpit_pipe_constructed (GObject *object) { CockpitPipe *self = COCKPIT_PIPE (object); GError *error = NULL; G_OBJECT_CLASS (cockpit_pipe_parent_class)->constructed (object); if (self->priv->in_fd >= 0) { if (!g_unix_set_fd_nonblocking (self->priv->in_fd, TRUE, &error)) { g_warning ("%s: couldn't set file descriptor to non-blocking: %s", self->priv->name, error->message); g_clear_error (&error); } self->priv->in_source = cockpit_unix_fd_source_new (self->priv->in_fd, G_IO_IN); g_source_set_name (self->priv->in_source, "pipe-input"); g_source_set_callback (self->priv->in_source, (GSourceFunc)dispatch_input, self, NULL); g_source_attach (self->priv->in_source, self->priv->context); } if (self->priv->out_fd >= 0) { if (!g_unix_set_fd_nonblocking (self->priv->out_fd, TRUE, &error)) { g_warning ("%s: couldn't set file descriptor to non-blocking: %s", self->priv->name, error->message); g_clear_error (&error); } start_output (self); } if (self->priv->err_fd >= 0) { if (!g_unix_set_fd_nonblocking (self->priv->err_fd, TRUE, &error)) { g_warning ("%s: couldn't set file descriptor to non-blocking: %s", self->priv->name, error->message); g_clear_error (&error); } self->priv->err_buffer = g_byte_array_new (); self->priv->err_source = cockpit_unix_fd_source_new (self->priv->err_fd, G_IO_IN); g_source_set_name (self->priv->err_source, "pipe-error"); g_source_set_callback (self->priv->err_source, (GSourceFunc)dispatch_error, self, NULL); g_source_attach (self->priv->err_source, self->priv->context); } if (self->priv->pid) { self->priv->is_process = TRUE; /* We may need this watch to outlast this process ... */ self->priv->watch_arg = g_new0 (CockpitPipe *, 1); *(self->priv->watch_arg) = self; self->priv->child = g_child_watch_source_new (self->priv->pid); g_source_set_callback (self->priv->child, (GSourceFunc)on_child_reap, self->priv->watch_arg, g_free); g_source_attach (self->priv->child, self->priv->context); }
static void * glib_ctx_add(void *ctx, const verto_ev *ev, verto_ev_flag *flags) { glib_ev *gev = NULL; GIOCondition cond = 0; verto_ev_type type = verto_get_type(ev); gev = g_new0(glib_ev, 1); if (!gev) return NULL; switch (type) { case VERTO_EV_TYPE_IO: #ifdef WIN32 gev->chan = g_io_channel_win32_new_socket(verto_get_fd(ev)); #else gev->chan = g_io_channel_unix_new(verto_get_fd(ev)); #endif if (!gev->chan) goto error; g_io_channel_set_close_on_unref(gev->chan, FALSE); if (*flags & VERTO_EV_FLAG_IO_READ) cond |= G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL; if (*flags & VERTO_EV_FLAG_IO_WRITE) cond |= G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL; gev->src = g_io_create_watch(gev->chan, cond); break; case VERTO_EV_TYPE_TIMEOUT: gev->src = g_timeout_source_new(verto_get_interval(ev)); break; case VERTO_EV_TYPE_IDLE: gev->src = g_idle_source_new(); break; case VERTO_EV_TYPE_CHILD: gev->src = g_child_watch_source_new(verto_get_proc(ev)); *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */ break; case VERTO_EV_TYPE_SIGNAL: #if GLIB_MAJOR_VERSION >= 2 #if GLIB_MINOR_VERSION >= 29 #ifdef G_OS_UNIX /* Not supported on Windows */ gev->src = g_unix_signal_source_new(verto_get_signal(ev)); break; #endif #endif /* GLIB_MINOR_VERSION >= 29 */ #endif /* GLIB_MAJOR_VERSION >= 2 */ default: return NULL; /* Not supported */ } if (!gev->src) goto error; if (type == VERTO_EV_TYPE_IO) g_source_set_callback(gev->src, (GSourceFunc) glib_callback_io, (void *) ev, NULL); else if (type == VERTO_EV_TYPE_CHILD) g_source_set_callback(gev->src, (GSourceFunc) glib_callback_child, (void *) ev, NULL); else g_source_set_callback(gev->src, glib_callback, (void *) ev, NULL); if (*flags & VERTO_EV_FLAG_PRIORITY_HIGH) g_source_set_priority(gev->src, G_PRIORITY_HIGH); else if (*flags & VERTO_EV_FLAG_PRIORITY_MEDIUM) g_source_set_priority(gev->src, G_PRIORITY_DEFAULT_IDLE); else if (*flags & VERTO_EV_FLAG_PRIORITY_LOW) g_source_set_priority(gev->src, G_PRIORITY_LOW); g_source_set_can_recurse(gev->src, FALSE); if (g_source_attach(gev->src, ((glib_ev_ctx*) ctx)->context) == 0) goto error; return gev; error: if (gev) { if (gev->chan) g_io_channel_unref(gev->chan); if (gev->src) { g_source_destroy(gev->src); g_source_unref(gev->src); } g_free(gev); } return NULL; }
static gint nm_openconnect_start_openconnect_binary (NMOPENCONNECTPlugin *plugin, NMSettingVPN *s_vpn, GError **error) { NMOPENCONNECTPluginPrivate *priv = NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin); GPid pid; const char **openconnect_binary = NULL; GPtrArray *openconnect_argv; GSource *openconnect_watch; gint stdin_fd; const char *props_vpn_gw, *props_cookie, *props_cacert, *props_mtu, *props_gwcert, *props_proxy; /* Find openconnect */ openconnect_binary = openconnect_binary_paths; while (*openconnect_binary != NULL) { if (g_file_test (*openconnect_binary, G_FILE_TEST_EXISTS)) break; openconnect_binary++; } if (!*openconnect_binary) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "%s", _("Could not find openconnect binary.")); return -1; } /* The actual gateway to use (after redirection) comes from the auth dialog, so it's in the secrets hash not the properties */ props_vpn_gw = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GATEWAY); if (!props_vpn_gw || !strlen (props_vpn_gw) ) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "%s", _("No VPN gateway specified.")); return -1; } props_cookie = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_COOKIE); if (!props_cookie || !strlen (props_cookie)) { g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "%s", _("No WebVPN cookie provided.")); return -1; } props_gwcert = nm_setting_vpn_get_secret (s_vpn, NM_OPENCONNECT_KEY_GWCERT); props_cacert = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_CACERT); props_mtu = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_MTU); props_proxy = nm_setting_vpn_get_data_item (s_vpn, NM_OPENCONNECT_KEY_PROXY); openconnect_argv = g_ptr_array_new (); g_ptr_array_add (openconnect_argv, (gpointer) (*openconnect_binary)); if (props_gwcert && strlen(props_gwcert)) { g_ptr_array_add (openconnect_argv, (gpointer) "--servercert"); g_ptr_array_add (openconnect_argv, (gpointer) props_gwcert); } else if (props_cacert && strlen(props_cacert)) { g_ptr_array_add (openconnect_argv, (gpointer) "--cafile"); g_ptr_array_add (openconnect_argv, (gpointer) props_cacert); } if (props_mtu && strlen(props_mtu)) { g_ptr_array_add (openconnect_argv, (gpointer) "--mtu"); g_ptr_array_add (openconnect_argv, (gpointer) props_mtu); } if (props_proxy && strlen(props_proxy)) { g_ptr_array_add (openconnect_argv, (gpointer) "--proxy"); g_ptr_array_add (openconnect_argv, (gpointer) props_proxy); } g_ptr_array_add (openconnect_argv, (gpointer) "--syslog"); g_ptr_array_add (openconnect_argv, (gpointer) "--cookie-on-stdin"); g_ptr_array_add (openconnect_argv, (gpointer) "--script"); g_ptr_array_add (openconnect_argv, (gpointer) NM_OPENCONNECT_HELPER_PATH); priv->tun_name = create_persistent_tundev (); if (priv->tun_name) { g_ptr_array_add (openconnect_argv, (gpointer) "--interface"); g_ptr_array_add (openconnect_argv, (gpointer) priv->tun_name); } g_ptr_array_add (openconnect_argv, (gpointer) props_vpn_gw); if (debug) g_ptr_array_add (openconnect_argv, (gpointer) "--verbose"); g_ptr_array_add (openconnect_argv, NULL); if (!g_spawn_async_with_pipes (NULL, (char **) openconnect_argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD, openconnect_drop_child_privs, priv->tun_name, &pid, &stdin_fd, NULL, NULL, error)) { g_ptr_array_free (openconnect_argv, TRUE); g_warning ("openconnect failed to start. error: '%s'", (*error)->message); return -1; } g_ptr_array_free (openconnect_argv, TRUE); g_message ("openconnect started with pid %d", pid); if (write(stdin_fd, props_cookie, strlen(props_cookie)) != strlen(props_cookie) || write(stdin_fd, "\n", 1) != 1) { g_warning ("openconnect didn't eat the cookie we fed it"); return -1; } close(stdin_fd); NM_OPENCONNECT_PLUGIN_GET_PRIVATE (plugin)->pid = pid; openconnect_watch = g_child_watch_source_new (pid); g_source_set_callback (openconnect_watch, (GSourceFunc) openconnect_watch_cb, plugin, NULL); g_source_attach (openconnect_watch, NULL); g_source_unref (openconnect_watch); return 0; }
void ForkExecParent::start() { if (m_watchChild) { SE_THROW("child already started"); } // boost::shared_ptr<ForkExecParent> me = ...; GDBusCXX::DBusErrorCXX dbusError; SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: preparing for child process %s", m_helper.c_str()); m_server = GDBusCXX::DBusServerCXX::listen("", &dbusError); if (!m_server) { dbusError.throwFailure("starting server"); } m_server->setNewConnectionCallback(boost::bind(&ForkExecParent::newClientConnection, this, _2)); // look for helper binary std::string helper; GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD; if (m_helper.find('/') == m_helper.npos) { helper = getEnv("SYNCEVOLUTION_LIBEXEC_DIR", ""); if (helper.empty()) { // env variable not set, look in libexec dir helper = SYNCEVO_LIBEXEC; helper += "/"; helper += m_helper; if (access(helper.c_str(), R_OK)) { // some error, try PATH flags = (GSpawnFlags)(flags | G_SPAWN_SEARCH_PATH); helper = m_helper; } } else { // use env variable without further checks, must work helper += "/"; helper += m_helper; } } else { // absolute path, use it helper = m_helper; } m_argvStrings.push_back(helper); m_argv.reset(AllocStringArray(m_argvStrings)); for (char **env = environ; *env; env++) { if (!boost::starts_with(*env, ForkExecEnvVar)) { m_envStrings.push_back(*env); } } // pass D-Bus address via env variable m_envStrings.push_back(ForkExecEnvVar + m_server->getAddress()); m_env.reset(AllocStringArray(m_envStrings)); SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: running %s with D-Bus address %s", helper.c_str(), m_server->getAddress().c_str()); // Check which kind of output redirection is wanted. m_mergedStdoutStderr = !m_onOutput.empty(); if (!m_onOutput.empty()) { m_mergedStdoutStderr = true; } GErrorCXX gerror; int err = -1, out = -1; if (!g_spawn_async_with_pipes(NULL, // working directory static_cast<gchar **>(m_argv.get()), static_cast<gchar **>(m_env.get()), flags, // child setup function: redirect stdout to stderr m_mergedStdoutStderr ? setStdoutToStderr : NULL, NULL, // child setup user data &m_childPid, NULL, // set stdin to /dev/null (m_mergedStdoutStderr || m_onStdout.empty()) ? NULL : &out, (m_mergedStdoutStderr || !m_onStderr.empty()) ? &err : NULL, gerror)) { m_childPid = 0; gerror.throwError("spawning child"); } // set up output redirection, ignoring failures setupPipe(m_err, m_errID, err); setupPipe(m_out, m_outID, out); SE_LOG_DEBUG(NULL, NULL, "ForkExecParent: child process for %s has pid %ld", helper.c_str(), (long)m_childPid); // TODO: introduce C++ wrapper around GSource m_watchChild = g_child_watch_source_new(m_childPid); g_source_set_callback(m_watchChild, (GSourceFunc)watchChildCallback, this, NULL); g_source_attach(m_watchChild, NULL); }
/* * starts gdb, collects commands and start the first one */ gboolean run(const gchar* file, const gchar* commandline, GList* env, GList *witer, GList *biter, const gchar* terminal_device, dbg_callbacks* callbacks) { GError *err = NULL; dbg_cbs = callbacks; /* spawn GDB */ const gchar *exclude[] = { "LANG", NULL }; gchar **gdb_env = utils_copy_environment(exclude, "LANG", "C", NULL); if (!g_spawn_async_with_pipes(NULL, (gchar**)gdb_args, gdb_env, GDB_SPAWN_FLAGS, NULL, NULL, &gdb_pid, &gdb_in, &gdb_out, NULL, &err)) { dbg_cbs->report_error(_("Failed to spawn gdb process")); return FALSE; } g_strfreev(gdb_env); /* move gdb to it's own process group */ setpgid(gdb_pid, 0); /* set handler for gdb process exit event */ g_child_watch_add(gdb_pid, on_gdb_exit, NULL); gdb_src = g_child_watch_source_new(gdb_pid); /* create GDB GIO chanels */ gdb_ch_in = g_io_channel_unix_new(gdb_in); gdb_ch_out = g_io_channel_unix_new(gdb_out); /* reading starting gdb messages */ GList *lines = read_until_prompt(); GList *line = lines; while (line) { gchar *unescaped = g_strcompress((gchar*)line->data); if (strlen(unescaped)) { colorize_message((gchar*)line->data); } line = line->next; } g_list_foreach(lines, (GFunc)g_free, NULL); g_list_free(lines); /* add initial watches to the list */ while (witer) { gchar *name = (gchar*)witer->data; variable *var = variable_new(name, VT_WATCH); watches = g_list_append(watches, var); witer = witer->next; } /* collect commands */ GList *commands = NULL; /* loading file */ GString *command = g_string_new(""); g_string_printf(command, "-file-exec-and-symbols %s", file); commands = add_to_queue(commands, _("~\"Loading target file ...\""), command->str, _("Error loading file"), FALSE); g_string_free(command, TRUE); /* setting asyncronous mode */ commands = add_to_queue(commands, NULL, "-gdb-set target-async 1", _("Error configuring GDB"), FALSE); /* setting null-stop array printing */ commands = add_to_queue(commands, NULL, "-interpreter-exec console \"set print null-stop\"", _("Error configuring GDB"), FALSE); /* enable pretty printing */ commands = add_to_queue(commands, NULL, "-enable-pretty-printing", _("Error configuring GDB"), FALSE); /* set locale */ command = g_string_new(""); g_string_printf(command, "-gdb-set environment LANG=%s", g_getenv("LANG")); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); /* set arguments */ command = g_string_new(""); g_string_printf(command, "-exec-arguments %s", commandline); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); /* set passed evironment */ GList *iter = env; while (iter) { gchar *name = (gchar*)iter->data; iter = iter->next; gchar *value = (gchar*)iter->data; command = g_string_new(""); g_string_printf(command, "-gdb-set environment %s=%s", name, value); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); iter = iter->next; } /* set breaks */ int bp_index = 1; while (biter) { breakpoint *bp = (breakpoint*)biter->data; command = g_string_new(""); g_string_printf(command, "-break-insert -f %s:%i", bp->file, bp->line); GString *error_message = g_string_new(""); g_string_printf(error_message, _("Breakpoint at %s:%i cannot be set\nDebugger message: %s"), bp->file, bp->line, "%s"); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); g_string_free(error_message, TRUE); if (bp->hitscount) { command = g_string_new(""); g_string_printf(command, "-break-after %i %i", bp_index, bp->hitscount); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); } if (strlen(bp->condition)) { command = g_string_new(""); g_string_printf (command, "-break-condition %i %s", bp_index, bp->condition); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); } if (!bp->enabled) { command = g_string_new(""); g_string_printf (command, "-break-disable %i", bp_index); commands = add_to_queue(commands, NULL, command->str, error_message->str, TRUE); g_string_free(command, TRUE); } bp_index++; biter = biter->next; } /* set debugging terminal */ command = g_string_new("-inferior-tty-set "); g_string_append(command, terminal_device); commands = add_to_queue(commands, NULL, command->str, NULL, FALSE); g_string_free(command, TRUE); /* connect read callback to the output chanel */ gdb_id_out = g_io_add_watch(gdb_ch_out, G_IO_IN, on_read_async_output, commands); queue_item *item = (queue_item*)commands->data; /* send message to debugger messages window */ if (item->message) { dbg_cbs->send_message(item->message->str, "grey"); } /* send first command */ gdb_input_write_line(item->command->str); return TRUE; }
static void ul_spawned_job_constructed (GObject *object) { UlSpawnedJob *self = UL_SPAWNED_JOB (object); GError *error; gchar *cmd; G_OBJECT_CLASS (ul_spawned_job_parent_class)->constructed (object); cmd = g_strjoinv (" ", self->argv); g_debug ("spawned job: %s", cmd); self->main_context = g_main_context_get_thread_default (); if (self->main_context != NULL) g_main_context_ref (self->main_context); /* could already be cancelled */ error = NULL; if (g_cancellable_set_error_if_cancelled (ul_job_get_cancellable (UL_JOB (self)), &error)) { emit_completed_with_error_in_idle (self, error); g_error_free (error); goto out; } self->cancellable_handler_id = g_cancellable_connect (ul_job_get_cancellable (UL_JOB (self)), G_CALLBACK (on_cancelled), self, NULL); error = NULL; if (!g_spawn_async_with_pipes (NULL, /* working directory */ self->argv, NULL, /* envp */ G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, child_setup, /* child_setup */ self, /* child_setup's user_data */ &(self->child_pid), self->input_string != NULL ? &(self->child_stdin_fd) : NULL, &(self->child_stdout_fd), &(self->child_stderr_fd), &error)) { g_prefix_error (&error, "Error spawning command-line `%s': ", cmd); emit_completed_with_error_in_idle (self, error); g_error_free (error); goto out; } self->child_watch_source = g_child_watch_source_new (self->child_pid); g_source_set_callback (self->child_watch_source, (GSourceFunc) child_watch_cb, self, NULL); g_source_attach (self->child_watch_source, self->main_context); g_source_unref (self->child_watch_source); if (self->child_stdin_fd != -1) { self->input_string_cursor = self->input_string; self->child_stdin_channel = g_io_channel_unix_new (self->child_stdin_fd); g_io_channel_set_flags (self->child_stdin_channel, G_IO_FLAG_NONBLOCK, NULL); self->child_stdin_source = g_io_create_watch (self->child_stdin_channel, G_IO_OUT); g_source_set_callback (self->child_stdin_source, (GSourceFunc) write_child_stdin, self, NULL); g_source_attach (self->child_stdin_source, self->main_context); g_source_unref (self->child_stdin_source); } self->child_stdout_channel = g_io_channel_unix_new (self->child_stdout_fd); g_io_channel_set_flags (self->child_stdout_channel, G_IO_FLAG_NONBLOCK, NULL); self->child_stdout_source = g_io_create_watch (self->child_stdout_channel, G_IO_IN); g_source_set_callback (self->child_stdout_source, (GSourceFunc) read_child_stdout, self, NULL); g_source_attach (self->child_stdout_source, self->main_context); g_source_unref (self->child_stdout_source); self->child_stderr_channel = g_io_channel_unix_new (self->child_stderr_fd); g_io_channel_set_flags (self->child_stderr_channel, G_IO_FLAG_NONBLOCK, NULL); self->child_stderr_source = g_io_create_watch (self->child_stderr_channel, G_IO_IN); g_source_set_callback (self->child_stderr_source, (GSourceFunc) read_child_stderr, self, NULL); g_source_attach (self->child_stderr_source, self->main_context); g_source_unref (self->child_stderr_source); out: g_free (cmd); }
static gint run_command (struct _CamelSExp *f, gint argc, struct _CamelSExpResult **argv, FilterMessageSearch *fms) { CamelMimeMessage *message; CamelStream *stream; gint i; gint pipe_to_child; GPid child_pid; GError *error = NULL; GPtrArray *args; child_watch_data_t child_watch_data; GSource *source; GMainContext *context; if (argc < 1 || argv[0]->value.string[0] == '\0') return 0; args = g_ptr_array_new (); for (i = 0; i < argc; i++) g_ptr_array_add (args, argv[i]->value.string); g_ptr_array_add (args, NULL); if (!g_spawn_async_with_pipes (NULL, (gchar **) args->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, child_setup_func, NULL, &child_pid, &pipe_to_child, NULL, NULL, &error)) { g_ptr_array_free (args, TRUE); g_set_error ( fms->error, CAMEL_ERROR, CAMEL_ERROR_GENERIC, _("Failed to create child process '%s': %s"), argv[0]->value.string, error->message); g_error_free (error); return -1; } g_ptr_array_free (args, TRUE); message = camel_filter_search_get_message (fms, f); stream = camel_stream_fs_new_with_fd (pipe_to_child); camel_data_wrapper_write_to_stream_sync ( CAMEL_DATA_WRAPPER (message), stream, NULL, NULL); camel_stream_flush (stream, NULL, NULL); g_object_unref (stream); context = g_main_context_new (); child_watch_data.loop = g_main_loop_new (context, FALSE); g_main_context_unref (context); source = g_child_watch_source_new (child_pid); g_source_set_callback (source, (GSourceFunc) child_watch, &child_watch_data, NULL); g_source_attach (source, g_main_loop_get_context (child_watch_data.loop)); g_source_unref (source); g_main_loop_run (child_watch_data.loop); g_main_loop_unref (child_watch_data.loop); #ifndef G_OS_WIN32 if (WIFEXITED (child_watch_data.child_status)) return WEXITSTATUS (child_watch_data.child_status); else return -1; #else return child_watch_data.child_status; #endif }
static void spawn_data_free (SpawnData *data) { if (data->timeout_source != NULL) { g_source_destroy (data->timeout_source); data->timeout_source = NULL; } /* Nuke the child, if necessary */ if (data->child_watch_source != NULL) { g_source_destroy (data->child_watch_source); data->child_watch_source = NULL; } if (data->child_pid != 0) { GSource *source; kill (data->child_pid, SIGTERM); /* OK, we need to reap for the child ourselves - we don't want * to use waitpid() because that might block the calling * thread (the child might handle SIGTERM and use several * seconds for cleanup/rollback). * * So we use GChildWatch instead. * * Avoid taking a references to ourselves. but note that we need * to pass the GSource so we can nuke it once handled. */ source = g_child_watch_source_new (data->child_pid); g_source_set_callback (source, (GSourceFunc) child_watch_from_release_cb, source, (GDestroyNotify) g_source_destroy); g_source_attach (source, data->main_context); g_source_unref (source); data->child_pid = 0; } if (data->child_stdout != NULL) { g_string_free (data->child_stdout, TRUE); data->child_stdout = NULL; } if (data->child_stderr != NULL) { g_string_free (data->child_stderr, TRUE); data->child_stderr = NULL; } if (data->child_stdout_channel != NULL) { g_io_channel_unref (data->child_stdout_channel); data->child_stdout_channel = NULL; } if (data->child_stderr_channel != NULL) { g_io_channel_unref (data->child_stderr_channel); data->child_stderr_channel = NULL; } if (data->child_stdout_source != NULL) { g_source_destroy (data->child_stdout_source); data->child_stdout_source = NULL; } if (data->child_stderr_source != NULL) { g_source_destroy (data->child_stderr_source); data->child_stderr_source = NULL; } if (data->child_stdout_fd != -1) { g_warn_if_fail (close (data->child_stdout_fd) == 0); data->child_stdout_fd = -1; } if (data->child_stderr_fd != -1) { g_warn_if_fail (close (data->child_stderr_fd) == 0); data->child_stderr_fd = -1; } if (data->cancellable_handler_id > 0) { g_cancellable_disconnect (data->cancellable, data->cancellable_handler_id); data->cancellable_handler_id = 0; } if (data->main_context != NULL) g_main_context_unref (data->main_context); if (data->cancellable != NULL) g_object_unref (data->cancellable); g_free (data->command_line); g_slice_free (SpawnData, data); }