static void setup_reload_pipe (DBusLoop *loop) { DBusError error; DBusWatch *watch; dbus_error_init (&error); if (!_dbus_full_duplex_pipe (&reload_pipe[0], &reload_pipe[1], TRUE, &error)) { _dbus_warn ("Unable to create reload pipe: %s\n", error.message); dbus_error_free (&error); exit (1); } _dbus_fd_set_close_on_exec (reload_pipe[0]); _dbus_fd_set_close_on_exec (reload_pipe[1]); watch = _dbus_watch_new (reload_pipe[RELOAD_READ_END], DBUS_WATCH_READABLE, TRUE, handle_reload_watch, NULL, NULL); if (watch == NULL) { _dbus_warn ("Unable to create reload watch: %s\n", error.message); dbus_error_free (&error); exit (1); } if (!_dbus_loop_add_watch (loop, watch, reload_watch_callback, NULL, NULL)) { _dbus_warn ("Unable to add reload watch to main loop: %s\n", error.message); dbus_error_free (&error); exit (1); } }
dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, char **argv, char **envp, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error) { DBusBabysitter *sitter; HANDLE sitter_thread; int sitter_thread_id; _DBUS_ASSERT_ERROR_IS_CLEAR (error); *sitter_p = NULL; PING(); sitter = _dbus_babysitter_new (); if (sitter == NULL) { _DBUS_SET_OOM (error); return FALSE; } sitter->child_setup = child_setup; sitter->user_data = user_data; sitter->executable = _dbus_strdup (argv[0]); if (sitter->executable == NULL) { _DBUS_SET_OOM (error); goto out0; } PING(); if (!_dbus_full_duplex_pipe (&sitter->socket_to_babysitter, &sitter->socket_to_main, FALSE, error)) goto out0; sitter->sitter_watch = _dbus_watch_new (sitter->socket_to_babysitter, DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); PING(); if (sitter->sitter_watch == NULL) { _DBUS_SET_OOM (error); goto out0; } PING(); if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch)) { _DBUS_SET_OOM (error); goto out0; } sitter->argc = protect_argv (argv, &sitter->argv); if (sitter->argc == -1) { _DBUS_SET_OOM (error); goto out0; } sitter->envp = envp; PING(); sitter_thread = (HANDLE) _beginthreadex (NULL, 0, babysitter, sitter, 0, &sitter_thread_id); if (sitter_thread == 0) { PING(); dbus_set_error_const (error, DBUS_ERROR_SPAWN_FORK_FAILED, "Failed to create new thread"); goto out0; } CloseHandle (sitter_thread); PING(); WaitForSingleObject (sitter->start_sync_event, INFINITE); PING(); if (sitter_p != NULL) *sitter_p = sitter; else _dbus_babysitter_unref (sitter); _DBUS_ASSERT_ERROR_IS_CLEAR (error); PING(); return TRUE; out0: _dbus_babysitter_unref (sitter); return FALSE; }
/** * Spawns a new process. The executable name and argv[0] * are the same, both are provided in argv[0]. The child_setup * function is passed the given user_data and is run in the child * just before calling exec(). * * Also creates a "babysitter" which tracks the status of the * child process, advising the parent if the child exits. * If the spawn fails, no babysitter is created. * If sitter_p is #NULL, no babysitter is kept. * * @param sitter_p return location for babysitter or #NULL * @param argv the executable and arguments * @param env the environment (not used on unix yet) * @param child_setup function to call in child pre-exec() * @param user_data user data for setup function * @param error error object to be filled in if function fails * @returns #TRUE on success, #FALSE if error is filled in */ dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, char **argv, char **env, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error) { DBusBabysitter *sitter; int child_err_report_pipe[2] = { -1, -1 }; int babysitter_pipe[2] = { -1, -1 }; pid_t pid; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (sitter_p != NULL) *sitter_p = NULL; sitter = NULL; sitter = _dbus_babysitter_new (); if (sitter == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } sitter->executable = _dbus_strdup (argv[0]); if (sitter->executable == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!make_pipe (child_err_report_pipe, error)) goto cleanup_and_fail; if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error)) goto cleanup_and_fail; /* Setting up the babysitter is only useful in the parent, * but we don't want to run out of memory and fail * after we've already forked, since then we'd leak * child processes everywhere. */ sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END], DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); if (sitter->error_watch == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch)) { /* we need to free it early so the destructor won't try to remove it * without it having been added, which DBusLoop doesn't allow */ _dbus_watch_invalidate (sitter->error_watch); _dbus_watch_unref (sitter->error_watch); sitter->error_watch = NULL; dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0], DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); if (sitter->sitter_watch == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch)) { /* we need to free it early so the destructor won't try to remove it * without it having been added, which DBusLoop doesn't allow */ _dbus_watch_invalidate (sitter->sitter_watch); _dbus_watch_unref (sitter->sitter_watch); sitter->sitter_watch = NULL; dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } _DBUS_ASSERT_ERROR_IS_CLEAR (error); pid = fork (); if (pid < 0) { dbus_set_error (error, DBUS_ERROR_SPAWN_FORK_FAILED, "Failed to fork (%s)", _dbus_strerror (errno)); goto cleanup_and_fail; } else if (pid == 0) { /* Immediate child, this is the babysitter process. */ int grandchild_pid; /* Be sure we crash if the parent exits * and we write to the err_report_pipe */ signal (SIGPIPE, SIG_DFL); /* Close the parent's end of the pipes. */ close_and_invalidate (&child_err_report_pipe[READ_END]); close_and_invalidate (&babysitter_pipe[0]); /* Create the child that will exec () */ grandchild_pid = fork (); if (grandchild_pid < 0) { write_err_and_exit (babysitter_pipe[1], CHILD_FORK_FAILED); _dbus_assert_not_reached ("Got to code after write_err_and_exit()"); } else if (grandchild_pid == 0) { do_exec (child_err_report_pipe[WRITE_END], argv, env, child_setup, user_data); _dbus_assert_not_reached ("Got to code after exec() - should have exited on error"); } else { babysit (grandchild_pid, babysitter_pipe[1]); _dbus_assert_not_reached ("Got to code after babysit()"); } } else { /* Close the uncared-about ends of the pipes */ close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[1]); sitter->socket_to_babysitter = babysitter_pipe[0]; babysitter_pipe[0] = -1; sitter->error_pipe_from_child = child_err_report_pipe[READ_END]; child_err_report_pipe[READ_END] = -1; sitter->sitter_pid = pid; if (sitter_p != NULL) *sitter_p = sitter; else _dbus_babysitter_unref (sitter); dbus_free_string_array (env); _DBUS_ASSERT_ERROR_IS_CLEAR (error); return TRUE; } cleanup_and_fail: _DBUS_ASSERT_ERROR_IS_SET (error); close_and_invalidate (&child_err_report_pipe[READ_END]); close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[0]); close_and_invalidate (&babysitter_pipe[1]); if (sitter != NULL) _dbus_babysitter_unref (sitter); return FALSE; }
/** * Creates the client-side transport for * a debug-pipe connection connected to the * given debug-pipe server name. * * @param server_name name of server to connect to * @param error address where an error can be returned. * @returns #NULL on no memory or transport */ DBusTransport* _dbus_transport_debug_pipe_new (const char *server_name, DBusError *error) { DBusTransport *client_transport; DBusTransport *server_transport; DBusConnection *connection; int client_fd, server_fd; DBusServer *server; DBusString address; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (server_pipe_hash == NULL) { dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); return NULL; } server = _dbus_hash_table_lookup_string (server_pipe_hash, server_name); if (server == NULL || ((DBusServerDebugPipe*)server)->disconnected) { dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL); return NULL; } if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (!_dbus_string_append (&address, "debug-pipe:name=") || !_dbus_string_append (&address, server_name)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_string_free (&address); return NULL; } if (!_dbus_full_duplex_pipe (&client_fd, &server_fd, FALSE, NULL)) { _dbus_verbose ("failed to create full duplex pipe\n"); dbus_set_error (error, DBUS_ERROR_FAILED, "Could not create full-duplex pipe"); _dbus_string_free (&address); return NULL; } _dbus_fd_set_close_on_exec (client_fd); _dbus_fd_set_close_on_exec (server_fd); client_transport = _dbus_transport_new_for_socket (client_fd, NULL, &address); if (client_transport == NULL) { _dbus_close_socket (client_fd, NULL); _dbus_close_socket (server_fd, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_string_free (&address); return NULL; } _dbus_string_free (&address); client_fd = -1; server_transport = _dbus_transport_new_for_socket (server_fd, &server->guid_hex, NULL); if (server_transport == NULL) { _dbus_transport_unref (client_transport); _dbus_close_socket (server_fd, NULL); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } server_fd = -1; if (!_dbus_transport_set_auth_mechanisms (server_transport, (const char**) server->auth_mechanisms)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_transport_unref (server_transport); _dbus_transport_unref (client_transport); return NULL; } connection = _dbus_connection_new_for_transport (server_transport); _dbus_transport_unref (server_transport); server_transport = NULL; if (connection == NULL) { _dbus_transport_unref (client_transport); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } /* See if someone wants to handle this new connection, * self-referencing for paranoia */ if (server->new_connection_function) { dbus_server_ref (server); (* server->new_connection_function) (server, connection, server->new_connection_data); dbus_server_unref (server); } /* If no one grabbed a reference, the connection will die, * and the client transport will get an immediate disconnect */ _dbus_connection_close_if_only_one_ref (connection); dbus_connection_unref (connection); return client_transport; }
EXPORT_C #endif dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p, char **argv, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error) { #ifndef __SYMBIAN32__ DBusBabysitter *sitter; int child_err_report_pipe[2] = { -1, -1 }; int babysitter_pipe[2] = { -1, -1 }; pid_t pid; #ifndef __SYMBIAN32__ _DBUS_ASSERT_ERROR_IS_CLEAR (error); *sitter_p = NULL; sitter = NULL; sitter = _dbus_babysitter_new (); if (sitter == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } sitter->executable = _dbus_strdup (argv[0]); if (sitter->executable == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!make_pipe (child_err_report_pipe, error)) goto cleanup_and_fail; _dbus_fd_set_close_on_exec (child_err_report_pipe[READ_END]); _dbus_fd_set_close_on_exec (child_err_report_pipe[WRITE_END]); if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error)) goto cleanup_and_fail; _dbus_fd_set_close_on_exec (babysitter_pipe[0]); _dbus_fd_set_close_on_exec (babysitter_pipe[1]); /* Setting up the babysitter is only useful in the parent, * but we don't want to run out of memory and fail * after we've already forked, since then we'd leak * child processes everywhere. */ sitter->error_watch = _dbus_watch_new (child_err_report_pipe[READ_END], DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); if (sitter->error_watch == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } sitter->sitter_watch = _dbus_watch_new (babysitter_pipe[0], DBUS_WATCH_READABLE, TRUE, handle_watch, sitter, NULL); if (sitter->sitter_watch == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto cleanup_and_fail; } _DBUS_ASSERT_ERROR_IS_CLEAR (error); pid = fork (); if (pid < 0) { dbus_set_error (error, DBUS_ERROR_SPAWN_FORK_FAILED, "Failed to fork (%s)", _dbus_strerror (errno)); goto cleanup_and_fail; } else if (pid == 0) { /* Immediate child, this is the babysitter process. */ int grandchild_pid; /* Be sure we crash if the parent exits * and we write to the err_report_pipe */ #ifndef __SYMBIAN32__ signal (SIGPIPE, SIG_DFL); #endif /* Close the parent's end of the pipes. */ close_and_invalidate (&child_err_report_pipe[READ_END]); close_and_invalidate (&babysitter_pipe[0]); /* Create the child that will exec () */ grandchild_pid = fork (); if (grandchild_pid < 0) { write_err_and_exit (babysitter_pipe[1], CHILD_FORK_FAILED); _dbus_assert_not_reached ("Got to code after write_err_and_exit()"); } else if (grandchild_pid == 0) { do_exec (child_err_report_pipe[WRITE_END], argv, child_setup, user_data); _dbus_assert_not_reached ("Got to code after exec() - should have exited on error"); } else { babysit (grandchild_pid, babysitter_pipe[1]); _dbus_assert_not_reached ("Got to code after babysit()"); } } else { /* Close the uncared-about ends of the pipes */ close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[1]); sitter->socket_to_babysitter = babysitter_pipe[0]; babysitter_pipe[0] = -1; sitter->error_pipe_from_child = child_err_report_pipe[READ_END]; child_err_report_pipe[READ_END] = -1; sitter->sitter_pid = pid; if (sitter_p != NULL) *sitter_p = sitter; else _dbus_babysitter_unref (sitter); _DBUS_ASSERT_ERROR_IS_CLEAR (error); return TRUE; } cleanup_and_fail: _DBUS_ASSERT_ERROR_IS_SET (error); close_and_invalidate (&child_err_report_pipe[READ_END]); close_and_invalidate (&child_err_report_pipe[WRITE_END]); close_and_invalidate (&babysitter_pipe[0]); close_and_invalidate (&babysitter_pipe[1]); if (sitter != NULL) _dbus_babysitter_unref (sitter); #endif return FALSE; #else /* FILE* ChildProcessStream; ChildProcessStream =popen(argv[0], "r"); if (ChildProcessStream == NULL) { dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, "Failed to execute service process"); return FALSE; } */ //static pid_t Childpid; //have to make it static for thread fuction to access it pid_t childPid; int retVal; //pthread_t thread; retVal = posix_spawn(&childPid, argv[0], NULL,NULL, NULL, NULL); if (retVal!=0) { dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED, "Failed to execute service process"); return FALSE; } /* pthread_create(&thread, NULL, (void*)&thread_fun, &Childpid); //(void) waitpid(Childpid, NULL, 0); //printf("\r\n*** Child process finished ***\r\n"); */ if(!retVal) return TRUE; else return FALSE; #endif }