D-Bus: dbus-spawn-test.c Source File

D-Bus 1.12.18

dbus-spawn-test.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-spawn-test.c
3 *
4 * Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
5 * Copyright (C) 2003 CodeFactory AB
6 * Copyright (C) 2005 Novell, Inc.
7 *
8 * Licensed under the Academic Free License version 2.1
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *
24 */
25 #include <config.h>
26
27
28 #include "dbus-spawn.h"
29 #include "dbus-sysdeps.h"
30 #include "dbus-test.h"
31
32 static char *
33 get_test_exec (const char *exe,
34 DBusString *scratch_space)
35 {
36 const char *dbus_test_exec;
37
38 dbus_test_exec = _dbus_getenv ("DBUS_TEST_EXEC");
39
40 if (dbus_test_exec == NULL)
41 return NULL;
42
43 if (!_dbus_string_init (scratch_space))
44 return NULL;
45
46 if (!_dbus_string_append_printf (scratch_space, "%s/%s%s",
47 dbus_test_exec, exe, DBUS_EXEEXT))
48 {
49 _dbus_string_free (scratch_space);
50 return NULL;
51 }
52
53 return _dbus_string_get_data (scratch_space);
54 }
55
56 static dbus_bool_t
57 check_spawn_nonexistent (void *data)
58 {
59 static const char arg_does_not_exist[] = "/this/does/not/exist/32542sdgafgafdg";
60
61 const char *argv[4] = { NULL, NULL, NULL, NULL };
62 DBusBabysitter *sitter = NULL;
63 DBusError error = DBUS_ERROR_INIT;
64
65 /*** Test launching nonexistent binary */
66
67 argv[0] = arg_does_not_exist;
68 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_nonexistent",
69 (char * const *) argv,
70 NULL, DBUS_SPAWN_NONE, NULL, NULL,
71 &error))
72 {
73 _dbus_babysitter_block_for_child_exit (sitter);
74 _dbus_babysitter_set_child_exit_error (sitter, &error);
75 }
76
77 if (sitter)
78 _dbus_babysitter_unref (sitter);
79
80 if (!dbus_error_is_set (&error))
81 {
82 _dbus_warn ("Did not get an error launching nonexistent executable");
83 return FALSE;
84 }
85
86 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
87 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
88 {
89 _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s",
90 error.name, error.message);
91 dbus_error_free (&error);
92 return FALSE;
93 }
94
95 dbus_error_free (&error);
96
97 return TRUE;
98 }
99
100 static dbus_bool_t
101 check_spawn_segfault (void *data)
102 {
103 char *argv[4] = { NULL, NULL, NULL, NULL };
104 DBusBabysitter *sitter = NULL;
105 DBusError error = DBUS_ERROR_INIT;
106 DBusString argv0;
107
108 /*** Test launching segfault binary */
109
110 argv[0] = get_test_exec ("test-segfault", &argv0);
111
112 if (argv[0] == NULL)
113 {
114 /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
115 return TRUE;
116 }
117
118 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
119 NULL, DBUS_SPAWN_NONE, NULL, NULL,
120 &error))
121 {
122 _dbus_babysitter_block_for_child_exit (sitter);
123 _dbus_babysitter_set_child_exit_error (sitter, &error);
124 }
125
126 _dbus_string_free (&argv0);
127
128 if (sitter)
129 _dbus_babysitter_unref (sitter);
130
131 if (!dbus_error_is_set (&error))
132 {
133 _dbus_warn ("Did not get an error launching segfaulting binary");
134 return FALSE;
135 }
136
137 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
138 #ifdef DBUS_WIN
139 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
140 #else
141 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
142 #endif
143 {
144 _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s",
145 error.name, error.message);
146 dbus_error_free (&error);
147 return FALSE;
148 }
149
150 dbus_error_free (&error);
151
152 return TRUE;
153 }
154
155 static dbus_bool_t
156 check_spawn_exit (void *data)
157 {
158 char *argv[4] = { NULL, NULL, NULL, NULL };
159 DBusBabysitter *sitter = NULL;
160 DBusError error = DBUS_ERROR_INIT;
161 DBusString argv0;
162
163 /*** Test launching exit failure binary */
164
165 argv[0] = get_test_exec ("test-exit", &argv0);
166
167 if (argv[0] == NULL)
168 {
169 /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
170 return TRUE;
171 }
172
173 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
174 NULL, DBUS_SPAWN_NONE, NULL, NULL,
175 &error))
176 {
177 _dbus_babysitter_block_for_child_exit (sitter);
178 _dbus_babysitter_set_child_exit_error (sitter, &error);
179 }
180
181 _dbus_string_free (&argv0);
182
183 if (sitter)
184 _dbus_babysitter_unref (sitter);
185
186 if (!dbus_error_is_set (&error))
187 {
188 _dbus_warn ("Did not get an error launching binary that exited with failure code");
189 return FALSE;
190 }
191
192 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
193 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
194 {
195 _dbus_warn ("Not expecting error when launching exiting executable: %s: %s",
196 error.name, error.message);
197 dbus_error_free (&error);
198 return FALSE;
199 }
200
201 dbus_error_free (&error);
202
203 return TRUE;
204 }
205
206 static dbus_bool_t
207 check_spawn_and_kill (void *data)
208 {
209 char *argv[4] = { NULL, NULL, NULL, NULL };
210 DBusBabysitter *sitter = NULL;
211 DBusError error = DBUS_ERROR_INIT;
212 DBusString argv0;
213
214 /*** Test launching sleeping binary then killing it */
215
216 argv[0] = get_test_exec ("test-sleep-forever", &argv0);
217
218 if (argv[0] == NULL)
219 {
220 /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
221 return TRUE;
222 }
223
224 if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
225 NULL, DBUS_SPAWN_NONE, NULL, NULL,
226 &error))
227 {
228 _dbus_babysitter_kill_child (sitter);
229
230 _dbus_babysitter_block_for_child_exit (sitter);
231
232 _dbus_babysitter_set_child_exit_error (sitter, &error);
233 }
234
235 _dbus_string_free (&argv0);
236
237 if (sitter)
238 _dbus_babysitter_unref (sitter);
239
240 if (!dbus_error_is_set (&error))
241 {
242 _dbus_warn ("Did not get an error after killing spawned binary");
243 return FALSE;
244 }
245
246 if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
247 #ifdef DBUS_WIN
248 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
249 #else
250 dbus_error_has_name (&error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
251 #endif
252 {
253 _dbus_warn ("Not expecting error when killing executable: %s: %s",
254 error.name, error.message);
255 dbus_error_free (&error);
256 return FALSE;
257 }
258
259 dbus_error_free (&error);
260
261 return TRUE;
262 }
263
264 dbus_bool_t
265 _dbus_spawn_test (const char *test_data_dir)
266 {
267 if (!_dbus_test_oom_handling ("spawn_nonexistent",
268 check_spawn_nonexistent,
269 NULL))
270 return FALSE;
271
272 if (!_dbus_test_oom_handling ("spawn_segfault",
273 check_spawn_segfault,
274 NULL))
275 return FALSE;
276
277 if (!_dbus_test_oom_handling ("spawn_exit",
278 check_spawn_exit,
279 NULL))
280 return FALSE;
281
282 if (!_dbus_test_oom_handling ("spawn_and_kill",
283 check_spawn_and_kill,
284 NULL))
285 return FALSE;
286
287 return TRUE;
288 }
dbus_error_has_name
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition: dbus-errors.c:302
DBusError::message
const char * message
public error message field
Definition: dbus-errors.h:51
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
DBUS_ERROR_SPAWN_EXEC_FAILED
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
Definition: dbus-protocol.h:416
DBUS_ERROR_SPAWN_CHILD_EXITED
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
Definition: dbus-protocol.h:420
DBUS_ERROR_INIT
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
dbus_error_free
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
DBUS_ERROR_SPAWN_CHILD_SIGNALED
#define DBUS_ERROR_SPAWN_CHILD_SIGNALED
While starting a new process, the child exited on a signal.
Definition: dbus-protocol.h:422
DBusString
Definition: dbus-string.h:42
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
_dbus_babysitter_kill_child
void _dbus_babysitter_kill_child(DBusBabysitter *sitter)
Blocks until the babysitter process gives us the PID of the spawned grandchild, then kills the spawne...
Definition: dbus-spawn.c:699
DBusBabysitter
Babysitter implementation details.
Definition: dbus-spawn-win.c:61
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition: dbus-internals.c:230
_dbus_spawn_async_with_babysitter
dbus_bool_t _dbus_spawn_async_with_babysitter(DBusBabysitter **sitter_p, const char *log_name, char *const *argv, char **env, DBusSpawnFlags flags, DBusSpawnChildSetupFunc child_setup, void *user_data, DBusError *error)
Spawns a new process.
Definition: dbus-spawn.c:1249
_dbus_string_append_printf
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1114
DBusError
Object representing an exception.
Definition: dbus-errors.h:48
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
TRUE
#define TRUE
Expands to "1".
DBusError::name
const char * name
public error name field
Definition: dbus-errors.h:50
_dbus_babysitter_unref
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn.c:329
DBUS_ERROR_NO_MEMORY
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
Definition: dbus-protocol.h:357
FALSE
#define FALSE
Expands to "0".
_dbus_babysitter_set_child_exit_error
void _dbus_babysitter_set_child_exit_error(DBusBabysitter *sitter, DBusError *error)
Sets the DBusError with an explanation of why the spawned child process exited (on a signal,...
Definition: dbus-spawn.c:770
_dbus_getenv
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:187
dbus_error_is_set
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329