aboutsummaryrefslogtreecommitdiff
path: root/src/testbed
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-03-11 14:44:45 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-03-11 14:44:45 +0000
commitdf768b66a2456c07b95f69f8b0dd57b12234a346 (patch)
tree9fa14ea6fbfec88e79b11fc8a22b174cc2dca5ab /src/testbed
parent7a7234e8565b7738e0b52f8cd7e2ffbb19cb1043 (diff)
downloadgnunet-df768b66a2456c07b95f69f8b0dd57b12234a346.tar.gz
gnunet-df768b66a2456c07b95f69f8b0dd57b12234a346.zip
- fix crash monitoring
Diffstat (limited to 'src/testbed')
-rw-r--r--src/testbed/gnunet-helper-testbed.c157
1 files changed, 95 insertions, 62 deletions
diff --git a/src/testbed/gnunet-helper-testbed.c b/src/testbed/gnunet-helper-testbed.c
index e4b836396..6df42c609 100644
--- a/src/testbed/gnunet-helper-testbed.c
+++ b/src/testbed/gnunet-helper-testbed.c
@@ -24,8 +24,13 @@
24 * gnunet-service-testbed. This binary also receives configuration 24 * gnunet-service-testbed. This binary also receives configuration
25 * from the remove controller which is put in a temporary location 25 * from the remove controller which is put in a temporary location
26 * with ports and paths fixed so that gnunet-service-testbed runs 26 * with ports and paths fixed so that gnunet-service-testbed runs
27 * without any hurdles. This binary also kills the testbed service 27 * without any hurdles.
28 * should the connection from the remote controller is dropped 28 *
29 * This helper monitors for three termination events. They are: (1)The
30 * stdin of the helper is closed for reading; (2)the helper received
31 * SIGTERM/SIGINT; (3)the testbed crashed. In case of events 1 and 2
32 * the helper kills the testbed service.
33 *
29 * @author Sree Harsha Totakura <sreeharsha@totakura.in> 34 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
30 */ 35 */
31 36
@@ -129,6 +134,11 @@ static GNUNET_SCHEDULER_TaskIdentifier write_task_id;
129static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id; 134static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id;
130 135
131/** 136/**
137 * shutdown task id
138 */
139static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
140
141/**
132 * Are we done reading messages from stdin? 142 * Are we done reading messages from stdin?
133 */ 143 */
134static int done_reading; 144static int done_reading;
@@ -140,13 +150,7 @@ static int status;
140 150
141 151
142/** 152/**
143 * Are we shutting down 153 * Task to shut down cleanly
144 */
145static int in_shutdown;
146
147
148/**
149 * Task to shutting down nicely
150 * 154 *
151 * @param cls NULL 155 * @param cls NULL
152 * @param tc the task context 156 * @param tc the task context
@@ -154,8 +158,13 @@ static int in_shutdown;
154static void 158static void
155shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 159shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
156{ 160{
157 LOG_DEBUG ("Shutting down\n"); 161 LOG_DEBUG ("Shutting down\n");
158 in_shutdown = GNUNET_YES; 162 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
163 if (NULL != testbed)
164 {
165 LOG_DEBUG ("Killing testbed\n");
166 GNUNET_break (0 == GNUNET_OS_process_kill (testbed, SIGTERM));
167 }
159 if (GNUNET_SCHEDULER_NO_TASK != read_task_id) 168 if (GNUNET_SCHEDULER_NO_TASK != read_task_id)
160 { 169 {
161 GNUNET_SCHEDULER_cancel (read_task_id); 170 GNUNET_SCHEDULER_cancel (read_task_id);
@@ -166,6 +175,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
166 GNUNET_SCHEDULER_cancel (write_task_id); 175 GNUNET_SCHEDULER_cancel (write_task_id);
167 write_task_id = GNUNET_SCHEDULER_NO_TASK; 176 write_task_id = GNUNET_SCHEDULER_NO_TASK;
168 } 177 }
178 if (GNUNET_SCHEDULER_NO_TASK != child_death_task_id)
179 {
180 GNUNET_SCHEDULER_cancel (child_death_task_id);
181 child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
182 }
169 if (NULL != stdin_fd) 183 if (NULL != stdin_fd)
170 (void) GNUNET_DISK_file_close (stdin_fd); 184 (void) GNUNET_DISK_file_close (stdin_fd);
171 if (NULL != stdout_fd) 185 if (NULL != stdout_fd)
@@ -174,13 +188,31 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
174 tokenizer = NULL; 188 tokenizer = NULL;
175 if (NULL != testbed) 189 if (NULL != testbed)
176 { 190 {
177 LOG_DEBUG ("Killing testbed\n"); 191 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (testbed));
178 GNUNET_break (0 == GNUNET_OS_process_kill (testbed, SIGTERM)); 192 GNUNET_OS_process_destroy (testbed);
193 testbed = NULL;
194 }
195 if (NULL != test_system)
196 {
197 GNUNET_TESTING_system_destroy (test_system, GNUNET_YES);
198 test_system = NULL;
179 } 199 }
180} 200}
181 201
182 202
183/** 203/**
204 * Scheduler shutdown task to be run now.
205 */
206static void
207shutdown_now (void)
208{
209 if (GNUNET_SCHEDULER_NO_TASK != shutdown_task_id)
210 GNUNET_SCHEDULER_cancel (shutdown_task_id);
211 shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
212}
213
214
215/**
184 * Task to write to the standard out 216 * Task to write to the standard out
185 * 217 *
186 * @param cls the WriteContext 218 * @param cls the WriteContext
@@ -224,6 +256,41 @@ write_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
224 256
225 257
226/** 258/**
259 * Task triggered whenever we receive a SIGCHLD (child
260 * process died).
261 *
262 * @param cls closure, NULL if we need to self-restart
263 * @param tc context
264 */
265static void
266child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
267{
268 const struct GNUNET_DISK_FileHandle *pr;
269 char c[16];
270
271 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
272 child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
273 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
274 {
275 child_death_task_id =
276 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
277 pr, &child_death_task, NULL);
278 return;
279 }
280 /* consume the signal */
281 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
282 LOG_DEBUG ("Child died\n");
283 if (NULL != testbed)
284 {
285 GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (testbed));
286 GNUNET_OS_process_destroy (testbed);
287 testbed = NULL;
288 }
289 shutdown_now ();
290}
291
292
293/**
227 * Functions with this signature are called whenever a 294 * Functions with this signature are called whenever a
228 * complete message is received by the tokenizer. 295 * complete message is received by the tokenizer.
229 * 296 *
@@ -363,12 +430,17 @@ tokenizer_cb (void *cls, void *client,
363 wc->data = reply; 430 wc->data = reply;
364 write_task_id = 431 write_task_id =
365 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_fd, 432 GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, stdout_fd,
366 &write_task, wc); 433 &write_task, wc);
434 child_death_task_id =
435 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
436 GNUNET_DISK_pipe_handle (sigpipe,
437 GNUNET_DISK_PIPE_END_READ),
438 &child_death_task, NULL);
367 return GNUNET_OK; 439 return GNUNET_OK;
368 440
369error: 441error:
370 status = GNUNET_SYSERR; 442 status = GNUNET_SYSERR;
371 GNUNET_SCHEDULER_shutdown (); 443 shutdown_now ();
372 return GNUNET_SYSERR; 444 return GNUNET_SYSERR;
373} 445}
374 446
@@ -391,13 +463,15 @@ read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
391 sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof (buf)); 463 sread = GNUNET_DISK_file_read (stdin_fd, buf, sizeof (buf));
392 if ((GNUNET_SYSERR == sread) || (0 == sread)) 464 if ((GNUNET_SYSERR == sread) || (0 == sread))
393 { 465 {
394 GNUNET_SCHEDULER_shutdown (); 466 LOG_DEBUG ("STDIN closed\n");
467 shutdown_now ();
395 return; 468 return;
396 } 469 }
397 if (GNUNET_YES == done_reading) 470 if (GNUNET_YES == done_reading)
398 { 471 {
399 /* didn't expect any more data! */ 472 /* didn't expect any more data! */
400 GNUNET_SCHEDULER_shutdown (); 473 GNUNET_break_op (0);
474 shutdown_now ();
401 return; 475 return;
402 } 476 }
403 LOG_DEBUG ("Read %u bytes\n", sread); 477 LOG_DEBUG ("Read %u bytes\n", sread);
@@ -406,7 +480,7 @@ read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
406 GNUNET_NO)) 480 GNUNET_NO))
407 { 481 {
408 GNUNET_break (0); 482 GNUNET_break (0);
409 GNUNET_SCHEDULER_shutdown (); 483 shutdown_now ();
410 return; 484 return;
411 } 485 }
412 read_task_id = /* No timeout while reading */ 486 read_task_id = /* No timeout while reading */
@@ -416,42 +490,6 @@ read_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
416 490
417 491
418/** 492/**
419 * Task triggered whenever we receive a SIGCHLD (child
420 * process died).
421 *
422 * @param cls closure, NULL if we need to self-restart
423 * @param tc context
424 */
425static void
426child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
427{
428 const struct GNUNET_DISK_FileHandle *pr;
429 char c[16];
430
431 pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
432 child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
433 if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
434 {
435 child_death_task_id =
436 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
437 pr, &child_death_task, NULL);
438 return;
439 }
440 /* consume the signal */
441 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
442 LOG_DEBUG ("Child died\n");
443 GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (testbed));
444 GNUNET_OS_process_destroy (testbed);
445 testbed = NULL;
446 if (NULL != test_system)
447 {
448 GNUNET_TESTING_system_destroy (test_system, GNUNET_YES);
449 test_system = NULL;
450 }
451}
452
453
454/**
455 * Main function that will be run. 493 * Main function that will be run.
456 * 494 *
457 * @param cls closure 495 * @param cls closure
@@ -470,13 +508,9 @@ run (void *cls, char *const *args, const char *cfgfile,
470 read_task_id = 508 read_task_id =
471 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fd, 509 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, stdin_fd,
472 &read_task, NULL); 510 &read_task, NULL);
473 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, 511 shutdown_task_id =
474 NULL); 512 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
475 child_death_task_id = 513 NULL);
476 GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
477 GNUNET_DISK_pipe_handle (sigpipe,
478 GNUNET_DISK_PIPE_END_READ),
479 &child_death_task, NULL);
480} 514}
481 515
482 516
@@ -516,7 +550,6 @@ main (int argc, char **argv)
516 int ret; 550 int ret;
517 551
518 status = GNUNET_OK; 552 status = GNUNET_OK;
519 in_shutdown = GNUNET_NO;
520 if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 553 if (NULL == (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO,
521 GNUNET_NO, GNUNET_NO))) 554 GNUNET_NO, GNUNET_NO)))
522 { 555 {