D-Bus  1.12.20
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 #ifdef HAVE_PDPLINUX
72  &error, NULL))
73 #else
74  &error))
75 #endif
76  {
77  _dbus_babysitter_block_for_child_exit (sitter);
79  }
80 
81  if (sitter)
82  _dbus_babysitter_unref (sitter);
83 
84  if (!dbus_error_is_set (&error))
85  {
86  _dbus_warn ("Did not get an error launching nonexistent executable");
87  return FALSE;
88  }
89 
90  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
92  {
93  _dbus_warn ("Not expecting error when launching nonexistent executable: %s: %s",
94  error.name, error.message);
95  dbus_error_free (&error);
96  return FALSE;
97  }
98 
99  dbus_error_free (&error);
100 
101  return TRUE;
102 }
103 
104 static dbus_bool_t
105 check_spawn_segfault (void *data)
106 {
107  char *argv[4] = { NULL, NULL, NULL, NULL };
108  DBusBabysitter *sitter = NULL;
109  DBusError error = DBUS_ERROR_INIT;
110  DBusString argv0;
111 
112  /*** Test launching segfault binary */
113 
114  argv[0] = get_test_exec ("test-segfault", &argv0);
115 
116  if (argv[0] == NULL)
117  {
118  /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
119  return TRUE;
120  }
121 
122  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_segfault", argv,
123  NULL, DBUS_SPAWN_NONE, NULL, NULL,
124 #ifdef HAVE_PDPLINUX
125  &error, NULL))
126 #else
127  &error))
128 #endif
129  {
130  _dbus_babysitter_block_for_child_exit (sitter);
131  _dbus_babysitter_set_child_exit_error (sitter, &error);
132  }
133 
134  _dbus_string_free (&argv0);
135 
136  if (sitter)
137  _dbus_babysitter_unref (sitter);
138 
139  if (!dbus_error_is_set (&error))
140  {
141  _dbus_warn ("Did not get an error launching segfaulting binary");
142  return FALSE;
143  }
144 
145  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
146 #ifdef DBUS_WIN
148 #else
150 #endif
151  {
152  _dbus_warn ("Not expecting error when launching segfaulting executable: %s: %s",
153  error.name, error.message);
154  dbus_error_free (&error);
155  return FALSE;
156  }
157 
158  dbus_error_free (&error);
159 
160  return TRUE;
161 }
162 
163 static dbus_bool_t
164 check_spawn_exit (void *data)
165 {
166  char *argv[4] = { NULL, NULL, NULL, NULL };
167  DBusBabysitter *sitter = NULL;
168  DBusError error = DBUS_ERROR_INIT;
169  DBusString argv0;
170 
171  /*** Test launching exit failure binary */
172 
173  argv[0] = get_test_exec ("test-exit", &argv0);
174 
175  if (argv[0] == NULL)
176  {
177  /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
178  return TRUE;
179  }
180 
181  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_exit", argv,
182  NULL, DBUS_SPAWN_NONE, NULL, NULL,
183 #ifdef HAVE_PDPLINUX
184  &error, NULL))
185 #else
186  &error))
187 #endif
188  {
189  _dbus_babysitter_block_for_child_exit (sitter);
190  _dbus_babysitter_set_child_exit_error (sitter, &error);
191  }
192 
193  _dbus_string_free (&argv0);
194 
195  if (sitter)
196  _dbus_babysitter_unref (sitter);
197 
198  if (!dbus_error_is_set (&error))
199  {
200  _dbus_warn ("Did not get an error launching binary that exited with failure code");
201  return FALSE;
202  }
203 
204  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
206  {
207  _dbus_warn ("Not expecting error when launching exiting executable: %s: %s",
208  error.name, error.message);
209  dbus_error_free (&error);
210  return FALSE;
211  }
212 
213  dbus_error_free (&error);
214 
215  return TRUE;
216 }
217 
218 static dbus_bool_t
219 check_spawn_and_kill (void *data)
220 {
221  char *argv[4] = { NULL, NULL, NULL, NULL };
222  DBusBabysitter *sitter = NULL;
223  DBusError error = DBUS_ERROR_INIT;
224  DBusString argv0;
225 
226  /*** Test launching sleeping binary then killing it */
227 
228  argv[0] = get_test_exec ("test-sleep-forever", &argv0);
229 
230  if (argv[0] == NULL)
231  {
232  /* OOM was simulated or DBUS_TEST_EXEC was unset; either is OK */
233  return TRUE;
234  }
235 
236  if (_dbus_spawn_async_with_babysitter (&sitter, "spawn_and_kill", argv,
237  NULL, DBUS_SPAWN_NONE, NULL, NULL,
238 #ifdef HAVE_PDPLINUX
239  &error, NULL))
240 #else
241  &error))
242 #endif
243  {
245 
246  _dbus_babysitter_block_for_child_exit (sitter);
247 
248  _dbus_babysitter_set_child_exit_error (sitter, &error);
249  }
250 
251  _dbus_string_free (&argv0);
252 
253  if (sitter)
254  _dbus_babysitter_unref (sitter);
255 
256  if (!dbus_error_is_set (&error))
257  {
258  _dbus_warn ("Did not get an error after killing spawned binary");
259  return FALSE;
260  }
261 
262  if (!(dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY) ||
263 #ifdef DBUS_WIN
265 #else
267 #endif
268  {
269  _dbus_warn ("Not expecting error when killing executable: %s: %s",
270  error.name, error.message);
271  dbus_error_free (&error);
272  return FALSE;
273  }
274 
275  dbus_error_free (&error);
276 
277  return TRUE;
278 }
279 
281 _dbus_spawn_test (const char *test_data_dir)
282 {
283  if (!_dbus_test_oom_handling ("spawn_nonexistent",
284  check_spawn_nonexistent,
285  NULL))
286  return FALSE;
287 
288  if (!_dbus_test_oom_handling ("spawn_segfault",
289  check_spawn_segfault,
290  NULL))
291  return FALSE;
292 
293  if (!_dbus_test_oom_handling ("spawn_exit",
294  check_spawn_exit,
295  NULL))
296  return FALSE;
297 
298  if (!_dbus_test_oom_handling ("spawn_and_kill",
299  check_spawn_and_kill,
300  NULL))
301  return FALSE;
302 
303  return TRUE;
304 }
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
#define NULL
A null pointer, defined appropriately for C or C++.
#define DBUS_ERROR_SPAWN_EXEC_FAILED
While starting a new process, the exec() call failed.
#define DBUS_ERROR_SPAWN_CHILD_EXITED
While starting a new process, the child exited with a status code.
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
void dbus_error_free(DBusError *error)
Frees an error that&#39;s been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
#define DBUS_ERROR_SPAWN_CHILD_SIGNALED
While starting a new process, the child exited on a signal.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
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:703
Babysitter implementation details.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
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:1273
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
Object representing an exception.
Definition: dbus-errors.h:48
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
#define TRUE
Expands to "1".
void _dbus_babysitter_unref(DBusBabysitter *sitter)
Decrement the reference count on the babysitter object.
Definition: dbus-spawn.c:333
#define DBUS_ERROR_NO_MEMORY
There was not enough memory to complete an operation.
#define FALSE
Expands to "0".
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:774
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:187
dbus_bool_t dbus_error_is_set(const DBusError *error)
Checks whether an error occurred (the error is set).
Definition: dbus-errors.c:329