diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-08-18 17:51:07 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-08-18 17:51:07 +0000 |
commit | eb4ebfca26250af0816abf08c5e3364de88c950a (patch) | |
tree | 990ea3bfcd78879667ccfa5c8773d3690044d009 /src/fs/gnunet-auto-share.c | |
parent | 36731df5428357af5abdae6065e75222d03d49fd (diff) | |
download | gnunet-eb4ebfca26250af0816abf08c5e3364de88c950a.tar.gz gnunet-eb4ebfca26250af0816abf08c5e3364de88c950a.zip |
adding some assertions to ensure we only start one gnunet-publish
Diffstat (limited to 'src/fs/gnunet-auto-share.c')
-rw-r--r-- | src/fs/gnunet-auto-share.c | 140 |
1 files changed, 92 insertions, 48 deletions
diff --git a/src/fs/gnunet-auto-share.c b/src/fs/gnunet-auto-share.c index 7a4cf53be..fc85b29e4 100644 --- a/src/fs/gnunet-auto-share.c +++ b/src/fs/gnunet-auto-share.c | |||
@@ -97,12 +97,12 @@ static int do_disable_creation_time; | |||
97 | /** | 97 | /** |
98 | * Handle for the 'shutdown' task. | 98 | * Handle for the 'shutdown' task. |
99 | */ | 99 | */ |
100 | static struct GNUNET_SCHEDULER_Task * kill_task; | 100 | static struct GNUNET_SCHEDULER_Task *kill_task; |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * Handle for the main task that does scanning and working. | 103 | * Handle for the main task that does scanning and working. |
104 | */ | 104 | */ |
105 | static struct GNUNET_SCHEDULER_Task * run_task; | 105 | static struct GNUNET_SCHEDULER_Task *run_task; |
106 | 106 | ||
107 | /** | 107 | /** |
108 | * Anonymity level option to use for publishing. | 108 | * Anonymity level option to use for publishing. |
@@ -135,13 +135,13 @@ static struct WorkItem *work_head; | |||
135 | static struct WorkItem *work_tail; | 135 | static struct WorkItem *work_tail; |
136 | 136 | ||
137 | /** | 137 | /** |
138 | * Map from the hash of the filename (!) to a 'struct WorkItem' | 138 | * Map from the hash of the filename (!) to a `struct WorkItem` |
139 | * that was finished. | 139 | * that was finished. |
140 | */ | 140 | */ |
141 | static struct GNUNET_CONTAINER_MultiHashMap *work_finished; | 141 | static struct GNUNET_CONTAINER_MultiHashMap *work_finished; |
142 | 142 | ||
143 | /** | 143 | /** |
144 | * Set to GNUNET_YES if we are shutting down. | 144 | * Set to #GNUNET_YES if we are shutting down. |
145 | */ | 145 | */ |
146 | static int do_shutdown; | 146 | static int do_shutdown; |
147 | 147 | ||
@@ -180,7 +180,7 @@ get_state_file () | |||
180 | 180 | ||
181 | 181 | ||
182 | /** | 182 | /** |
183 | * Load the set of 'work_finished' items from disk. | 183 | * Load the set of #work_finished items from disk. |
184 | */ | 184 | */ |
185 | static void | 185 | static void |
186 | load_state () | 186 | load_state () |
@@ -241,12 +241,12 @@ load_state () | |||
241 | 241 | ||
242 | 242 | ||
243 | /** | 243 | /** |
244 | * Write work item from the work_finished map to the given write handle. | 244 | * Write work item from the #work_finished map to the given write handle. |
245 | * | 245 | * |
246 | * @param cls the 'struct GNUNET_BIO_WriteHandle*' | 246 | * @param cls the `struct GNUNET_BIO_WriteHandle *` |
247 | * @param key key of the item in the map (unused) | 247 | * @param key key of the item in the map (unused) |
248 | * @param value the 'struct WorkItem' to write | 248 | * @param value the `struct WorkItem` to write |
249 | * @return GNUNET_OK to continue to iterate (if write worked) | 249 | * @return #GNUNET_OK to continue to iterate (if write worked) |
250 | */ | 250 | */ |
251 | static int | 251 | static int |
252 | write_item (void *cls, | 252 | write_item (void *cls, |
@@ -272,7 +272,7 @@ write_item (void *cls, | |||
272 | 272 | ||
273 | 273 | ||
274 | /** | 274 | /** |
275 | * Save the set of 'work_finished' items on disk. | 275 | * Save the set of #work_finished items on disk. |
276 | */ | 276 | */ |
277 | static void | 277 | static void |
278 | save_state () | 278 | save_state () |
@@ -320,13 +320,15 @@ save_state () | |||
320 | * @param tc scheduler context, unused | 320 | * @param tc scheduler context, unused |
321 | */ | 321 | */ |
322 | static void | 322 | static void |
323 | do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 323 | do_stop_task (void *cls, |
324 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
324 | { | 325 | { |
325 | kill_task = NULL; | 326 | kill_task = NULL; |
326 | do_shutdown = GNUNET_YES; | 327 | do_shutdown = GNUNET_YES; |
327 | if (NULL != publish_proc) | 328 | if (NULL != publish_proc) |
328 | { | 329 | { |
329 | GNUNET_OS_process_kill (publish_proc, SIGKILL); | 330 | GNUNET_OS_process_kill (publish_proc, |
331 | SIGKILL); | ||
330 | return; | 332 | return; |
331 | } | 333 | } |
332 | if (NULL != run_task) | 334 | if (NULL != run_task) |
@@ -348,11 +350,12 @@ schedule_next_task (void); | |||
348 | * Task triggered whenever we receive a SIGCHLD (child | 350 | * Task triggered whenever we receive a SIGCHLD (child |
349 | * process died). | 351 | * process died). |
350 | * | 352 | * |
351 | * @param cls the 'struct WorkItem' we were working on | 353 | * @param cls the `struct WorkItem` we were working on |
352 | * @param tc context | 354 | * @param tc context |
353 | */ | 355 | */ |
354 | static void | 356 | static void |
355 | maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 357 | maint_child_death (void *cls, |
358 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
356 | { | 359 | { |
357 | struct WorkItem *wi = cls; | 360 | struct WorkItem *wi = cls; |
358 | struct GNUNET_HashCode key; | 361 | struct GNUNET_HashCode key; |
@@ -362,15 +365,17 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
362 | char c; | 365 | char c; |
363 | const struct GNUNET_DISK_FileHandle *pr; | 366 | const struct GNUNET_DISK_FileHandle *pr; |
364 | 367 | ||
365 | |||
366 | run_task = NULL; | 368 | run_task = NULL; |
367 | pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); | 369 | pr = GNUNET_DISK_pipe_handle (sigpipe, |
370 | GNUNET_DISK_PIPE_END_READ); | ||
368 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) | 371 | if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY)) |
369 | { | 372 | { |
370 | /* shutdown scheduled us, ignore! */ | 373 | /* shutdown scheduled us, someone else will kill child, |
374 | we should just try again */ | ||
371 | run_task = | 375 | run_task = |
372 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | 376 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
373 | pr, &maint_child_death, wi); | 377 | pr, |
378 | &maint_child_death, wi); | ||
374 | return; | 379 | return; |
375 | } | 380 | } |
376 | 381 | ||
@@ -380,10 +385,17 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
380 | GNUNET_assert (GNUNET_SYSERR != ret); | 385 | GNUNET_assert (GNUNET_SYSERR != ret); |
381 | if (GNUNET_NO == ret) | 386 | if (GNUNET_NO == ret) |
382 | { | 387 | { |
388 | /* process still running? Well, how did we get here? | ||
389 | Anyway, answer is to kill it! */ | ||
383 | GNUNET_break (0); | 390 | GNUNET_break (0); |
384 | GNUNET_OS_process_kill (publish_proc, SIGKILL); | 391 | GNUNET_OS_process_kill (publish_proc, |
385 | type = GNUNET_OS_PROCESS_SIGNALED; | 392 | SIGKILL); |
393 | ret = GNUNET_OS_process_status (publish_proc, | ||
394 | &type, | ||
395 | &code); | ||
386 | } | 396 | } |
397 | GNUNET_assert (GNUNET_OK == ret); | ||
398 | |||
387 | GNUNET_OS_process_destroy (publish_proc); | 399 | GNUNET_OS_process_destroy (publish_proc); |
388 | publish_proc = NULL; | 400 | publish_proc = NULL; |
389 | /* consume the signal */ | 401 | /* consume the signal */ |
@@ -433,7 +445,8 @@ sighandler_child_death () | |||
433 | 445 | ||
434 | GNUNET_break (1 == | 446 | GNUNET_break (1 == |
435 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle | 447 | GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle |
436 | (sigpipe, GNUNET_DISK_PIPE_END_WRITE), | 448 | (sigpipe, |
449 | GNUNET_DISK_PIPE_END_WRITE), | ||
437 | &c, sizeof (c))); | 450 | &c, sizeof (c))); |
438 | errno = old_errno; /* restore errno */ | 451 | errno = old_errno; /* restore errno */ |
439 | } | 452 | } |
@@ -489,6 +502,7 @@ work (void *cls, | |||
489 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 502 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
490 | _("Publishing `%s'\n"), | 503 | _("Publishing `%s'\n"), |
491 | wi->filename); | 504 | wi->filename); |
505 | GNUNET_assert (NULL == publish_proc); | ||
492 | publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES, | 506 | publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES, |
493 | 0, NULL, NULL, NULL, | 507 | 0, NULL, NULL, NULL, |
494 | "gnunet-publish", | 508 | "gnunet-publish", |
@@ -506,10 +520,12 @@ work (void *cls, | |||
506 | NULL); | 520 | NULL); |
507 | return; | 521 | return; |
508 | } | 522 | } |
509 | pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); | 523 | pr = GNUNET_DISK_pipe_handle (sigpipe, |
524 | GNUNET_DISK_PIPE_END_READ); | ||
510 | run_task = | 525 | run_task = |
511 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | 526 | GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, |
512 | pr, &maint_child_death, wi); | 527 | pr, |
528 | &maint_child_death, wi); | ||
513 | } | 529 | } |
514 | 530 | ||
515 | 531 | ||
@@ -519,7 +535,7 @@ work (void *cls, | |||
519 | * | 535 | * |
520 | * @param cls where to store the unique ID we are computing | 536 | * @param cls where to store the unique ID we are computing |
521 | * @param filename file to scan | 537 | * @param filename file to scan |
522 | * @return GNUNET_OK (always) | 538 | * @return #GNUNET_OK (always) |
523 | */ | 539 | */ |
524 | static int | 540 | static int |
525 | determine_id (void *cls, | 541 | determine_id (void *cls, |
@@ -532,10 +548,14 @@ determine_id (void *cls, | |||
532 | 548 | ||
533 | if (0 != STAT (filename, &sbuf)) | 549 | if (0 != STAT (filename, &sbuf)) |
534 | { | 550 | { |
535 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "stat", filename); | 551 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, |
552 | "stat", | ||
553 | filename); | ||
536 | return GNUNET_OK; | 554 | return GNUNET_OK; |
537 | } | 555 | } |
538 | GNUNET_CRYPTO_hash (filename, strlen (filename), &fx[0]); | 556 | GNUNET_CRYPTO_hash (filename, |
557 | strlen (filename), | ||
558 | &fx[0]); | ||
539 | if (!S_ISDIR (sbuf.st_mode)) | 559 | if (!S_ISDIR (sbuf.st_mode)) |
540 | { | 560 | { |
541 | uint64_t fattr[2]; | 561 | uint64_t fattr[2]; |
@@ -543,21 +563,29 @@ determine_id (void *cls, | |||
543 | fattr[0] = GNUNET_htonll (sbuf.st_size); | 563 | fattr[0] = GNUNET_htonll (sbuf.st_size); |
544 | fattr[0] = GNUNET_htonll (sbuf.st_mtime); | 564 | fattr[0] = GNUNET_htonll (sbuf.st_mtime); |
545 | 565 | ||
546 | GNUNET_CRYPTO_hash (fattr, sizeof (fattr), &fx[1]); | 566 | GNUNET_CRYPTO_hash (fattr, |
567 | sizeof (fattr), | ||
568 | &fx[1]); | ||
547 | } | 569 | } |
548 | else | 570 | else |
549 | { | 571 | { |
550 | memset (&fx[1], 1, sizeof (struct GNUNET_HashCode)); | 572 | memset (&fx[1], |
573 | 1, | ||
574 | sizeof (struct GNUNET_HashCode)); | ||
551 | GNUNET_DISK_directory_scan (filename, | 575 | GNUNET_DISK_directory_scan (filename, |
552 | &determine_id, | 576 | &determine_id, |
553 | &fx[1]); | 577 | &fx[1]); |
554 | } | 578 | } |
555 | /* use hash here to make hierarchical structure distinct from | 579 | /* use hash here to make hierarchical structure distinct from |
556 | all files on the same level */ | 580 | all files on the same level */ |
557 | GNUNET_CRYPTO_hash (fx, sizeof (fx), &ft); | 581 | GNUNET_CRYPTO_hash (fx, |
582 | sizeof (fx), | ||
583 | &ft); | ||
558 | /* use XOR here so that order of the files in the directory | 584 | /* use XOR here so that order of the files in the directory |
559 | does not matter! */ | 585 | does not matter! */ |
560 | GNUNET_CRYPTO_hash_xor (&ft, id, id); | 586 | GNUNET_CRYPTO_hash_xor (&ft, |
587 | id, | ||
588 | id); | ||
561 | return GNUNET_OK; | 589 | return GNUNET_OK; |
562 | } | 590 | } |
563 | 591 | ||
@@ -569,7 +597,7 @@ determine_id (void *cls, | |||
569 | * | 597 | * |
570 | * @param cls closure, NULL | 598 | * @param cls closure, NULL |
571 | * @param filename complete filename (absolute path) | 599 | * @param filename complete filename (absolute path) |
572 | * @return GNUNET_OK to continue to iterate, GNUNET_SYSERR during shutdown | 600 | * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR during shutdown |
573 | */ | 601 | */ |
574 | static int | 602 | static int |
575 | add_file (void *cls, | 603 | add_file (void *cls, |
@@ -627,7 +655,8 @@ add_file (void *cls, | |||
627 | * @param tc scheduler context, unused | 655 | * @param tc scheduler context, unused |
628 | */ | 656 | */ |
629 | static void | 657 | static void |
630 | scan (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | 658 | scan (void *cls, |
659 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
631 | { | 660 | { |
632 | run_task = NULL; | 661 | run_task = NULL; |
633 | start_time = GNUNET_TIME_absolute_get (); | 662 | start_time = GNUNET_TIME_absolute_get (); |
@@ -648,6 +677,7 @@ schedule_next_task () | |||
648 | 677 | ||
649 | if (GNUNET_YES == do_shutdown) | 678 | if (GNUNET_YES == do_shutdown) |
650 | return; | 679 | return; |
680 | GNUNET_assert (NULL == run_task); | ||
651 | if (NULL == work_head) | 681 | if (NULL == work_head) |
652 | { | 682 | { |
653 | /* delay by at most 4h, at least 1s, and otherwise in between depending | 683 | /* delay by at most 4h, at least 1s, and otherwise in between depending |
@@ -664,7 +694,8 @@ schedule_next_task () | |||
664 | } | 694 | } |
665 | else | 695 | else |
666 | { | 696 | { |
667 | run_task = GNUNET_SCHEDULER_add_now (&work, NULL); | 697 | run_task = GNUNET_SCHEDULER_add_now (&work, |
698 | NULL); | ||
668 | } | 699 | } |
669 | } | 700 | } |
670 | 701 | ||
@@ -678,12 +709,17 @@ schedule_next_task () | |||
678 | * @param c configuration | 709 | * @param c configuration |
679 | */ | 710 | */ |
680 | static void | 711 | static void |
681 | run (void *cls, char *const *args, const char *cfgfile, | 712 | run (void *cls, |
713 | char *const *args, | ||
714 | const char *cfgfile, | ||
682 | const struct GNUNET_CONFIGURATION_Handle *c) | 715 | const struct GNUNET_CONFIGURATION_Handle *c) |
683 | { | 716 | { |
684 | /* check arguments */ | 717 | /* check arguments */ |
685 | if ((args[0] == NULL) || (args[1] != NULL) || | 718 | if ( (NULL == args[0]) || |
686 | (GNUNET_YES != GNUNET_DISK_directory_test (args[0], GNUNET_YES))) | 719 | (NULL != args[1]) || |
720 | (GNUNET_YES != | ||
721 | GNUNET_DISK_directory_test (args[0], | ||
722 | GNUNET_YES)) ) | ||
687 | { | 723 | { |
688 | printf (_("You must specify one and only one directory name for automatic publication.\n")); | 724 | printf (_("You must specify one and only one directory name for automatic publication.\n")); |
689 | ret = -1; | 725 | ret = -1; |
@@ -692,13 +728,15 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
692 | cfg_filename = GNUNET_strdup (cfgfile); | 728 | cfg_filename = GNUNET_strdup (cfgfile); |
693 | cfg = c; | 729 | cfg = c; |
694 | dir_name = args[0]; | 730 | dir_name = args[0]; |
695 | work_finished = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); | 731 | work_finished = GNUNET_CONTAINER_multihashmap_create (1024, |
732 | GNUNET_NO); | ||
696 | load_state (); | 733 | load_state (); |
697 | run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, | 734 | run_task = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, |
698 | &scan, NULL); | 735 | &scan, |
699 | 736 | NULL); | |
700 | kill_task = | 737 | kill_task = |
701 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, | 738 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, |
739 | &do_stop_task, | ||
702 | NULL); | 740 | NULL); |
703 | } | 741 | } |
704 | 742 | ||
@@ -708,8 +746,8 @@ run (void *cls, char *const *args, const char *cfgfile, | |||
708 | * | 746 | * |
709 | * @param cls NULL (unused) | 747 | * @param cls NULL (unused) |
710 | * @param key key of the item in the map (unused) | 748 | * @param key key of the item in the map (unused) |
711 | * @param value the 'struct WorkItem' to free | 749 | * @param value the `struct WorkItem` to free |
712 | * @return GNUNET_OK to continue to iterate | 750 | * @return #GNUNET_OK to continue to iterate |
713 | */ | 751 | */ |
714 | static int | 752 | static int |
715 | free_item (void *cls, | 753 | free_item (void *cls, |
@@ -760,14 +798,18 @@ main (int argc, char *const *argv) | |||
760 | int ok; | 798 | int ok; |
761 | struct GNUNET_SIGNAL_Context *shc_chld; | 799 | struct GNUNET_SIGNAL_Context *shc_chld; |
762 | 800 | ||
763 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | 801 | if (GNUNET_OK != |
802 | GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
764 | return 2; | 803 | return 2; |
765 | sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); | 804 | sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, |
766 | GNUNET_assert (sigpipe != NULL); | 805 | GNUNET_NO, GNUNET_NO); |
806 | GNUNET_assert (NULL != sigpipe); | ||
767 | shc_chld = | 807 | shc_chld = |
768 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); | 808 | GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, |
809 | &sighandler_child_death); | ||
769 | ok = (GNUNET_OK == | 810 | ok = (GNUNET_OK == |
770 | GNUNET_PROGRAM_run (argc, argv, "gnunet-auto-share [OPTIONS] FILENAME", | 811 | GNUNET_PROGRAM_run (argc, argv, |
812 | "gnunet-auto-share [OPTIONS] FILENAME", | ||
771 | gettext_noop | 813 | gettext_noop |
772 | ("Automatically publish files from a directory on GNUnet"), | 814 | ("Automatically publish files from a directory on GNUnet"), |
773 | options, &run, NULL)) ? ret : 1; | 815 | options, &run, NULL)) ? ret : 1; |
@@ -780,7 +822,9 @@ main (int argc, char *const *argv) | |||
780 | } | 822 | } |
781 | while (NULL != (wi = work_head)) | 823 | while (NULL != (wi = work_head)) |
782 | { | 824 | { |
783 | GNUNET_CONTAINER_DLL_remove (work_head, work_tail, wi); | 825 | GNUNET_CONTAINER_DLL_remove (work_head, |
826 | work_tail, | ||
827 | wi); | ||
784 | GNUNET_free (wi->filename); | 828 | GNUNET_free (wi->filename); |
785 | GNUNET_free (wi); | 829 | GNUNET_free (wi); |
786 | } | 830 | } |