static void check_babysit_events (pid_t grandchild_pid, int parent_pipe, int revents) { pid_t ret; int status; do { ret = waitpid (grandchild_pid, &status, WNOHANG); /* The man page says EINTR can't happen with WNOHANG, * but there are reports of it (maybe only with valgrind?) */ } while (ret < 0 && errno == EINTR); if (ret == 0) { _dbus_verbose ("no child exited\n"); ; /* no child exited */ } else if (ret < 0) { /* This isn't supposed to happen. */ _dbus_warn ("unexpected waitpid() failure in check_babysit_events(): %s\n", _dbus_strerror (errno)); exit (1); } else if (ret == grandchild_pid) { /* Child exited */ _dbus_verbose ("reaped child pid %ld\n", (long) ret); write_status_and_exit (parent_pipe, status); } else { _dbus_warn ("waitpid() reaped pid %d that we've never heard of\n", (int) ret); exit (1); } if (revents & _DBUS_POLLIN) { _dbus_verbose ("babysitter got POLLIN from parent pipe\n"); } if (revents & (_DBUS_POLLERR | _DBUS_POLLHUP)) { /* Parent is gone, so we just exit */ _dbus_verbose ("babysitter got POLLERR or POLLHUP from parent\n"); exit (0); } }
static dbus_bool_t check_spawn_and_kill (void *data) { char *argv[4] = { NULL, NULL, NULL, NULL }; DBusBabysitter *sitter = NULL; DBusError error = DBUS_ERROR_INIT; DBusString argv0; /*** Test launching sleeping binary then killing it */ argv[0] = get_test_exec ("test-sleep-forever", &argv0); if (argv[0] == NULL) { /* OOM was simulated, never mind */ return TRUE; } if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv, NULL, NULL, NULL, &error)) { _dbus_babysitter_kill_child (sitter); _dbus_babysitter_block_for_child_exit (sitter); _dbus_babysitter_set_child_exit_error (sitter, &error); } _dbus_string_free (&argv0); if (sitter) _dbus_babysitter_unref (sitter); if (!dbus_error_is_set (&error)) { _dbus_warn ("Did not get an error after killing spawned binary\n"); return FALSE; } if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED))) { _dbus_warn ("Not expecting error when killing executable: %s: %s\n", error.name, error.message); dbus_error_free (&error); return FALSE; } dbus_error_free (&error); return TRUE; }
static dbus_bool_t check_spawn_exit (void *data) { char *argv[4] = { NULL, NULL, NULL, NULL }; DBusBabysitter *sitter; DBusError error; sitter = NULL; dbus_error_init (&error); /*** Test launching exit failure binary */ argv[0] = TEST_EXIT_BINARY; if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, NULL, &error)) { #ifdef __SYMBIAN32__ if(sitter) { #endif _dbus_babysitter_block_for_child_exit (sitter); _dbus_babysitter_set_child_exit_error (sitter, &error); #ifdef __SYMBIAN32__ } #endif /* no baby sitter support in Symbian */ } if (sitter) _dbus_babysitter_unref (sitter); if (!dbus_error_is_set (&error)) { _dbus_warn ("Did not get an error launching binary that exited with failure code\n"); return FALSE; } if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED))) { _dbus_warn ("Not expecting error when launching exiting executable: %s: %s\n", error.name, error.message); dbus_error_free (&error); return FALSE; } dbus_error_free (&error); return TRUE; }
BusContext* bus_context_new_test (const DBusString *test_data_dir, const char *filename) { DBusError error; DBusString config_file; DBusString relative; BusContext *context; if (!_dbus_string_init (&config_file)) { _dbus_warn ("No memory\n"); return NULL; } if (!_dbus_string_copy (test_data_dir, 0, &config_file, 0)) { _dbus_warn ("No memory\n"); _dbus_string_free (&config_file); return NULL; } _dbus_string_init_const (&relative, filename); if (!_dbus_concat_dir_and_file (&config_file, &relative)) { _dbus_warn ("No memory\n"); _dbus_string_free (&config_file); return NULL; } dbus_error_init (&error); context = bus_context_new (&config_file, BUS_CONTEXT_FLAG_NONE, NULL, NULL, NULL, &error); if (context == NULL) { _DBUS_ASSERT_ERROR_IS_SET (&error); _dbus_warn ("Failed to create debug bus context from configuration file %s: %s\n", filename, error.message); dbus_error_free (&error); _dbus_string_free (&config_file); return NULL; } _dbus_string_free (&config_file); return context; }
static dbus_bool_t do_load (const DBusString *full_path, Validity validity, dbus_bool_t oom_possible) { BusConfigParser *parser; DBusError error; dbus_error_init (&error); parser = bus_config_load (full_path, TRUE, NULL, &error); if (parser == NULL) { _DBUS_ASSERT_ERROR_IS_SET (&error); if (oom_possible && dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) { _dbus_verbose ("Failed to load valid file due to OOM\n"); dbus_error_free (&error); return TRUE; } else if (validity == VALID) { _dbus_warn ("Failed to load valid file but still had memory: %s\n", error.message); dbus_error_free (&error); return FALSE; } else { dbus_error_free (&error); return TRUE; } } else { _DBUS_ASSERT_ERROR_IS_CLEAR (&error); bus_config_parser_unref (parser); if (validity == INVALID) { _dbus_warn ("Accepted invalid file\n"); return FALSE; } return TRUE; } }
dbus_bool_t _dbus_server_test (void) { const char *valid_addresses[] = { "tcp:port=1234", "tcp:host=localhost,port=1234", "tcp:host=localhost,port=1234;tcp:port=5678", #ifdef DBUS_UNIX "unix:path=./boogie", "tcp:port=1234;unix:path=./boogie", #endif }; DBusServer *server; int i; for (i = 0; i < _DBUS_N_ELEMENTS (valid_addresses); i++) { DBusError error = DBUS_ERROR_INIT; char *address; char *id; server = dbus_server_listen (valid_addresses[i], &error); if (server == NULL) { _dbus_warn ("server listen error: %s: %s\n", error.name, error.message); dbus_error_free (&error); _dbus_assert_not_reached ("Failed to listen for valid address."); } id = dbus_server_get_id (server); _dbus_assert (id != NULL); address = dbus_server_get_address (server); _dbus_assert (address != NULL); if (strstr (address, id) == NULL) { _dbus_warn ("server id '%s' is not in the server address '%s'\n", id, address); _dbus_assert_not_reached ("bad server id or address"); } dbus_free (id); dbus_free (address); dbus_server_disconnect (server); dbus_server_unref (server); } return TRUE; }
static dbus_bool_t check_have_valid_message (DBusMessageLoader *loader) { DBusMessage *message; dbus_bool_t retval; message = NULL; retval = FALSE; if (_dbus_message_loader_get_is_corrupted (loader)) { _dbus_warn ("loader corrupted on message that was expected to be valid; invalid reason %d\n", loader->corruption_reason); goto failed; } message = _dbus_message_loader_pop_message (loader); if (message == NULL) { _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n"); goto failed; } if (_dbus_string_get_length (&loader->data) > 0) { _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n"); goto failed; } #if 0 /* FIXME */ /* Verify that we're able to properly deal with the message. * For example, this would detect improper handling of messages * in nonstandard byte order. */ if (!check_message_handling (message)) goto failed; #endif record_validity_seen (DBUS_VALID); retval = TRUE; failed: if (message) dbus_message_unref (message); return retval; }
void _dbus_loop_remove_timeout (DBusLoop *loop, DBusTimeout *timeout, DBusTimeoutFunction function, void *data) { DBusList *link; link = _dbus_list_get_first_link (&loop->callbacks); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); Callback *this = link->data; if (this->type == CALLBACK_TIMEOUT && TIMEOUT_CALLBACK (this)->timeout == timeout && this->data == data && TIMEOUT_CALLBACK (this)->function == function) { remove_callback (loop, link); return; } link = next; } _dbus_warn ("could not find timeout %p function %p data %p to remove\n", timeout, (void *)function, data); }
void _dbus_loop_remove_watch (DBusLoop *loop, DBusWatch *watch, DBusWatchFunction function, void *data) { DBusList *link; link = _dbus_list_get_first_link (&loop->callbacks); while (link != NULL) { DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link); Callback *this = link->data; if (this->type == CALLBACK_WATCH && WATCH_CALLBACK (this)->watch == watch && this->data == data && WATCH_CALLBACK (this)->function == function) { remove_callback (loop, link); return; } link = next; } _dbus_warn ("could not find watch %p function %p data %p to remove\n", watch, (void *)function, data); }
static void check_dirname (const char *filename, const char *dirname) { DBusString f, d; _dbus_string_init_const (&f, filename); if (!_dbus_string_init (&d)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_get_dirname (&f, &d)) _dbus_assert_not_reached ("no memory"); if (!_dbus_string_equal_c_str (&d, dirname)) { _dbus_warn ("For filename \"%s\" got dirname \"%s\" and expected \"%s\"\n", filename, _dbus_string_get_const_data (&d), dirname); exit (1); } _dbus_string_free (&d); }
static void signal_handler (int sig) { switch (sig) { #ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX case SIGIO: /* explicit fall-through */ #endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */ #ifdef SIGHUP case SIGHUP: { DBusString str; _dbus_string_init_const (&str, "foo"); if ((reload_pipe[RELOAD_WRITE_END] > 0) && !_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1)) { _dbus_warn ("Unable to write to reload pipe.\n"); close_reload_pipe (); } } break; #endif } }
static void babysit (pid_t grandchild_pid, int parent_pipe) { int sigchld_pipe[2]; /* We don't exec, so we keep parent state, such as the pid that * _dbus_verbose() uses. Reset the pid here. */ _dbus_verbose_reset (); /* I thought SIGCHLD would just wake up the poll, but * that didn't seem to work, so added this pipe. * Probably the pipe is more likely to work on busted * operating systems anyhow. */ if (pipe (sigchld_pipe) < 0) { _dbus_warn ("Not enough file descriptors to create pipe in babysitter process\n"); exit (1); } babysit_sigchld_pipe = sigchld_pipe[WRITE_END]; #ifndef __SYMBIAN32__ _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler); #endif write_pid (parent_pipe, grandchild_pid); check_babysit_events (grandchild_pid, parent_pipe, 0); while (TRUE) { DBusPollFD pfds[2]; pfds[0].fd = parent_pipe; pfds[0].events = _DBUS_POLLIN; pfds[0].revents = 0; pfds[1].fd = sigchld_pipe[READ_END]; pfds[1].events = _DBUS_POLLIN; pfds[1].revents = 0; _dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1); if (pfds[0].revents != 0) { check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents); } else if (pfds[1].revents & _DBUS_POLLIN) { char b; read (sigchld_pipe[READ_END], &b, 1); /* do waitpid check */ check_babysit_events (grandchild_pid, parent_pipe, 0); } } exit (1); }
/** * Handles a watch by reading data, writing data, or disconnecting * the transport, as appropriate for the given condition. * * @param transport the transport. * @param watch the watch. * @param condition the current state of the watched file descriptor. * @returns #FALSE if not enough memory to fully handle the watch */ dbus_bool_t _dbus_transport_handle_watch (DBusTransport *transport, DBusWatch *watch, unsigned int condition) { dbus_bool_t retval; _dbus_assert (transport->vtable->handle_watch != NULL); if (transport->disconnected) return TRUE; if (dbus_watch_get_fd (watch) < 0) { _dbus_warn ("Tried to handle an invalidated watch; this watch should have been removed\n"); return TRUE; } _dbus_watch_sanitize_condition (watch, &condition); _dbus_transport_ref (transport); _dbus_watch_ref (watch); retval = (* transport->vtable->handle_watch) (transport, watch, condition); _dbus_watch_unref (watch); _dbus_transport_unref (transport); return retval; }
/* returns true if good things happen, or if we get OOM */ static dbus_bool_t bus_activation_helper_oom_test (void *data, dbus_bool_t have_memory) { const char *service; DBusError error; dbus_bool_t retval; service = (const char *) data; retval = TRUE; dbus_error_init (&error); if (!run_launch_helper (service, &error)) { _DBUS_ASSERT_ERROR_IS_SET (&error); /* we failed, but a OOM is good */ if (!dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) { _dbus_warn ("FAILED SELF TEST: Error: %s", error.message); retval = FALSE; } dbus_error_free (&error); } else { /* we succeeded, yay! */ _DBUS_ASSERT_ERROR_IS_CLEAR (&error); } return retval; }
static void do_write (int fd, const void *buf, size_t count) { size_t bytes_written; int ret; bytes_written = 0; again: ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written); if (ret < 0) { if (errno == EINTR) goto again; else { _dbus_warn ("Failed to write data to pipe!"); exit (1); /* give up, we suck */ } } else bytes_written += ret; if (bytes_written < count) goto again; }
static void signal_handler (int sig) { DBusString str; switch (sig) { #ifdef DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX case SIGIO: /* explicit fall-through */ #endif /* DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX */ case SIGHUP: _dbus_string_init_const (&str, "foo"); if (!_dbus_write_socket (reload_pipe[RELOAD_WRITE_END], &str, 0, 1)) { _dbus_warn ("Unable to write to reload pipe.\n"); exit (1); } break; case SIGTERM: _dbus_loop_quit (bus_context_get_loop (context)); break; } }
static void run_validity_tests (const ValidityTest *tests, int n_tests, DBusValidity (* func) (const DBusString*,int,int)) { int i; for (i = 0; i < n_tests; i++) { DBusString str; DBusValidity v; _dbus_string_init_const (&str, tests[i].data); v = (*func) (&str, 0, _dbus_string_get_length (&str)); if (v != tests[i].expected) { _dbus_warn ("Improper validation result %d for '%s'\n", v, tests[i].data); _dbus_assert_not_reached ("test failed"); } ++i; } }
/** * Loads the message in the given message file. * * @param filename filename to load * @param data string to load message into * @returns #TRUE if the message was loaded */ dbus_bool_t dbus_internal_do_not_use_load_message_file (const DBusString *filename, DBusString *data) { dbus_bool_t retval; DBusError error = DBUS_ERROR_INIT; retval = FALSE; _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename)); if (!_dbus_file_get_contents (data, filename, &error)) { _dbus_warn ("Could not load message file %s: %s\n", _dbus_string_get_const_data (filename), error.message); dbus_error_free (&error); goto failed; } retval = TRUE; failed: return retval; }
/** * Tries loading the message in the given message file * and verifies that DBusMessageLoader can handle it. * * @param filename filename to load * @param expected_validity what the message has to be like to return #TRUE * @returns #TRUE if the message has the expected validity */ dbus_bool_t dbus_internal_do_not_use_try_message_file (const DBusString *filename, DBusValidity expected_validity) { DBusString data; dbus_bool_t retval; retval = FALSE; if (!_dbus_string_init (&data)) _dbus_assert_not_reached ("could not allocate string\n"); if (!dbus_internal_do_not_use_load_message_file (filename, &data)) goto failed; retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity); failed: if (!retval) { if (_dbus_string_get_length (&data) > 0) _dbus_verbose_bytes_of_string (&data, 0, _dbus_string_get_length (&data)); _dbus_warn ("Failed message loader test on %s\n", _dbus_string_get_const_data (filename)); } _dbus_string_free (&data); return retval; }
static dbus_bool_t check_spawn_and_kill (void *data) { char *argv[4] = { NULL, NULL, NULL, NULL }; DBusBabysitter *sitter; DBusError error; sitter = NULL; dbus_error_init (&error); /*** Test launching sleeping binary then killing it */ argv[0] = TEST_SLEEP_FOREVER_BINARY; if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, NULL, NULL, &error)) { _dbus_babysitter_kill_child (sitter); _dbus_babysitter_block_for_child_exit (sitter); _dbus_babysitter_set_child_exit_error (sitter, &error); } if (sitter) _dbus_babysitter_unref (sitter); if (!dbus_error_is_set (&error)) { _dbus_warn ("Did not get an error after killing spawned binary\n"); return FALSE; } if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED))) { _dbus_warn ("Not expecting error when killing executable: %s: %s\n", error.name, error.message); dbus_error_free (&error); return FALSE; } dbus_error_free (&error); return TRUE; }
static int _init_kqueue (BusContext *context) { int ret = 0; if (kq < 0) { kq = kqueue (); if (kq < 0) { _dbus_warn ("Cannot create kqueue; error '%s'\n", _dbus_strerror (errno)); goto out; } loop = bus_context_get_loop (context); watch = _dbus_watch_new (kq, DBUS_WATCH_READABLE, TRUE, _handle_kqueue_watch, NULL, NULL); if (watch == NULL) { _dbus_warn ("Unable to create kqueue watch\n"); close (kq); kq = -1; goto out; } if (!_dbus_loop_add_watch (loop, watch)) { _dbus_warn ("Unable to add reload watch to main loop"); _dbus_watch_invalidate (watch); _dbus_watch_unref (watch); watch = NULL; close (kq); kq = -1; goto out; } } ret = 1; out: return ret; }
/* convenience function, do not reuse outside of TEST */ static dbus_bool_t make_full_path (const DBusString *test_data_dir, const char *subdir, const char *file, DBusString *full_path) { DBusString filename; dbus_bool_t retval; retval = FALSE; if (!_dbus_string_init (full_path)) { _dbus_warn ("couldn't allocate full path"); goto finish; } if (!_dbus_string_copy (test_data_dir, 0, full_path, 0)) { _dbus_warn ("couldn't allocate full path"); goto finish; } _dbus_string_init_const (&filename, subdir); if (!_dbus_concat_dir_and_file (full_path, &filename)) { _dbus_warn ("couldn't allocate full path"); goto finish; } _dbus_string_free (&filename); _dbus_string_init_const (&filename, file); if (!_dbus_concat_dir_and_file (full_path, &filename)) { _dbus_warn ("couldn't allocate full path"); goto finish; } /* woot! */ retval = TRUE; finish: _dbus_string_free (&filename); return retval; }
/** * Internals of _dbus_assert_not_reached(); it's a function * rather than a macro with the inline code so * that the assertion failure blocks don't show up * in test suite coverage, and to shrink code size. * * @param explanation what was reached that shouldn't have been * @param file file the assertion is in * @param line line the assertion is in */ void _dbus_real_assert_not_reached (const char *explanation, const char *file, int line) { _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n", file, line, _dbus_pid_for_log (), explanation); _dbus_abort (); }
static dbus_bool_t check_spawn_nonexistent (void *data) { char *argv[4] = { NULL, NULL, NULL, NULL }; DBusBabysitter *sitter; DBusError error; sitter = NULL; dbus_error_init (&error); /*** Test launching nonexistent binary */ argv[0] = "/this/does/not/exist/32542sdgafgafdg"; if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, NULL, NULL, &error)) { _dbus_babysitter_block_for_child_exit (sitter); _dbus_babysitter_set_child_exit_error (sitter, &error); } if (sitter) _dbus_babysitter_unref (sitter); if (!dbus_error_is_set (&error)) { _dbus_warn ("Did not get an error launching nonexistent executable\n"); return FALSE; } if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED))) { _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s\n", error.name, error.message); dbus_error_free (&error); return FALSE; } dbus_error_free (&error); return TRUE; }
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); } }
/** * Tests how well the given function responds to out-of-memory * situations. Calls the function repeatedly, failing a different * call to malloc() each time. If the function ever returns #FALSE, * the test fails. The function should return #TRUE whenever something * valid (such as returning an error, or succeeding) occurs, and #FALSE * if it gets confused in some way. * * @param description description of the test used in verbose output * @param func function to call * @param data data to pass to function * @returns #TRUE if the function never returns FALSE */ dbus_bool_t _dbus_test_oom_handling (const char *description, DBusTestMemoryFunction func, void *data) { int approx_mallocs; const char *setting; int max_failures_to_try; int i; /* Run once to see about how many mallocs are involved */ _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); _dbus_verbose ("Running once to count mallocs\n"); if (!(* func) (data)) return FALSE; approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter (); _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n", description, approx_mallocs); setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES"); if (setting != NULL) { DBusString str; long v; _dbus_string_init_const (&str, setting); v = 4; if (!_dbus_string_parse_int (&str, 0, &v, NULL)) _dbus_warn ("couldn't parse '%s' as integer\n", setting); max_failures_to_try = v; } else { max_failures_to_try = 4; } i = setting ? max_failures_to_try - 1 : 1; while (i < max_failures_to_try) { _dbus_set_fail_alloc_failures (i); if (!run_failing_each_malloc (approx_mallocs, description, func, data)) return FALSE; ++i; } _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n", description); return TRUE; }
static void _dbus_keyring_unlock (DBusKeyring *keyring) { DBusError error; dbus_error_init (&error); if (!_dbus_delete_file (&keyring->filename_lock, &error)) { _dbus_warn ("Failed to delete lock file: %s\n", error.message); dbus_error_free (&error); } }
static void check_memleaks (void) { dbus_shutdown (); if (_dbus_get_malloc_blocks_outstanding () != 0) { _dbus_warn ("%d dbus_malloc blocks were not freed in %s\n", _dbus_get_malloc_blocks_outstanding (), __FILE__); _dbus_assert_not_reached ("memleaks"); } }
static dbus_bool_t check_spawn_segfault (void *data) { char *argv[4] = { NULL, NULL, NULL, NULL }; DBusBabysitter *sitter = NULL; DBusError error = DBUS_ERROR_INIT; /*** Test launching segfault binary */ argv[0] = TEST_SEGFAULT_BINARY; if (_dbus_spawn_async_with_babysitter (&sitter, argv, NULL, NULL, NULL, &error)) { _dbus_babysitter_block_for_child_exit (sitter); _dbus_babysitter_set_child_exit_error (sitter, &error); } if (sitter) _dbus_babysitter_unref (sitter); if (!dbus_error_is_set (&error)) { _dbus_warn ("Did not get an error launching segfaulting binary\n"); return FALSE; } if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) || dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED))) { _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s\n", error.name, error.message); dbus_error_free (&error); return FALSE; } dbus_error_free (&error); return TRUE; }
static void check_memleaks (void) { dbus_shutdown (); printf ("%s: checking for memleaks\n", "dbus-test"); if (_dbus_get_malloc_blocks_outstanding () != 0) { _dbus_warn ("%d dbus_malloc blocks were not freed\n", _dbus_get_malloc_blocks_outstanding ()); die ("memleaks"); } }