diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-04-20 11:35:45 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-04-20 12:18:41 +0300 |
commit | 44a3ae866bf949b0ca5106ecfb8c5e3fda4b9af8 (patch) | |
tree | 5eb53b9505aba56a58848faf15ea7c2b996f7fb0 | |
parent | e8caefcc1b1a19abfca6a1e0a7dfea4af2761b53 (diff) | |
download | fileserv-44a3ae866bf949b0ca5106ecfb8c5e3fda4b9af8.tar.gz fileserv-44a3ae866bf949b0ca5106ecfb8c5e3fda4b9af8.tar.bz2 |
Start a sentinel process by default.
* src/fileserv.c (http_server)
(http_sentinel): New functions.
(main): New command line option -s (single process).
Start sentinel unless -s is given.
-rw-r--r-- | src/fileserv.c | 206 |
1 files changed, 168 insertions, 38 deletions
diff --git a/src/fileserv.c b/src/fileserv.c index f354460..fece526 100644 --- a/src/fileserv.c +++ b/src/fileserv.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include "mimetypes.h" | 18 | #include "mimetypes.h" |
19 | #include <string.h> | 19 | #include <string.h> |
20 | #include <errno.h> | 20 | #include <errno.h> |
21 | #include <sys/types.h> | ||
22 | #include <sys/wait.h> | ||
21 | #include <sys/select.h> | 23 | #include <sys/select.h> |
22 | #include <netdb.h> | 24 | #include <netdb.h> |
23 | #include <signal.h> | 25 | #include <signal.h> |
@@ -25,7 +27,6 @@ | |||
25 | #include <time.h> | 27 | #include <time.h> |
26 | #include <ctype.h> | 28 | #include <ctype.h> |
27 | 29 | ||
28 | |||
29 | #ifndef DEFAULT_ADDRESS | 30 | #ifndef DEFAULT_ADDRESS |
30 | # define DEFAULT_ADDRESS "0.0.0.0" | 31 | # define DEFAULT_ADDRESS "0.0.0.0" |
31 | #endif | 32 | #endif |
@@ -605,22 +606,167 @@ fileserv_error_printer (char const *msg) | |||
605 | error("%s", msg); | 606 | error("%s", msg); |
606 | } | 607 | } |
607 | 608 | ||
609 | static int fatal_signals[] = { | ||
610 | SIGHUP, | ||
611 | SIGINT, | ||
612 | SIGQUIT, | ||
613 | SIGTERM, | ||
614 | 0 | ||
615 | }; | ||
616 | |||
617 | static void | ||
618 | http_server(int fd, struct sockaddr *server_addr) | ||
619 | { | ||
620 | struct MHD_Daemon *mhd; | ||
621 | sigset_t sigs; | ||
622 | int i; | ||
623 | |||
624 | /* Block the 'fatal signals' and SIGPIPE in the handling thread */ | ||
625 | sigemptyset(&sigs); | ||
626 | for (i = 0; fatal_signals[i]; i++) | ||
627 | sigaddset(&sigs, fatal_signals[i]); | ||
628 | sigaddset(&sigs, SIGPIPE); | ||
629 | |||
630 | pthread_sigmask(SIG_BLOCK, &sigs, NULL); | ||
631 | MHD_set_panic_func(fileserv_panic, NULL); | ||
632 | |||
633 | mhd = MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD | ||
634 | | MHD_USE_ERROR_LOG, 0, | ||
635 | fileserv_acl, server_addr, | ||
636 | fileserv_handler, NULL, | ||
637 | MHD_OPTION_LISTEN_SOCKET, fd, | ||
638 | MHD_OPTION_EXTERNAL_LOGGER, fileserv_logger, | ||
639 | NULL, | ||
640 | MHD_OPTION_END); | ||
641 | /* Unblock only the fatal signals */ | ||
642 | sigdelset(&sigs, SIGPIPE); | ||
643 | pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); | ||
644 | /* Wait for signal to arrive */ | ||
645 | sigwait(&sigs, &i); | ||
646 | MHD_stop_daemon(mhd); | ||
647 | } | ||
648 | |||
649 | enum state { | ||
650 | RUNNING, /* Program is running */ | ||
651 | TERMINATING, /* Program is terminating */ | ||
652 | CHILD_TERM, /* SIGTERM has been sent to the child */ | ||
653 | CHILD_KILL | ||
654 | }; | ||
655 | volatile enum state state; | ||
656 | |||
657 | static void | ||
658 | sigterm(int sig) | ||
659 | { | ||
660 | if (state == RUNNING) | ||
661 | state = TERMINATING; | ||
662 | } | ||
663 | |||
664 | static void | ||
665 | sigalrm(int sig) | ||
666 | { | ||
667 | if (state == CHILD_TERM) | ||
668 | state = CHILD_KILL; | ||
669 | } | ||
670 | |||
671 | static void | ||
672 | http_sentinel(int fd, struct sockaddr *server_addr) | ||
673 | { | ||
674 | pid_t pid = 0; | ||
675 | int i; | ||
676 | struct sigaction act; | ||
677 | |||
678 | act.sa_flags = 0; | ||
679 | sigemptyset(&act.sa_mask); | ||
680 | |||
681 | act.sa_handler = sigalrm; | ||
682 | sigaction(SIGALRM, &act, NULL); | ||
683 | |||
684 | for (i = 0; fatal_signals[i]; i++) | ||
685 | sigaddset(&act.sa_mask, fatal_signals[i]); | ||
686 | act.sa_handler = sigterm; | ||
687 | for (i = 0; fatal_signals[i]; i++) | ||
688 | sigaction(fatal_signals[i], &act, NULL); | ||
689 | |||
690 | while (1) { | ||
691 | int status; | ||
692 | pid_t child_pid; | ||
693 | |||
694 | if (pid == 0) { | ||
695 | if (state != RUNNING) | ||
696 | break; | ||
697 | pid = fork(); | ||
698 | if (pid == -1) { | ||
699 | error("fork: %s", strerror(errno)); | ||
700 | break; | ||
701 | } | ||
702 | if (pid == 0) { | ||
703 | runas(user, group); | ||
704 | http_server(fd, server_addr); | ||
705 | exit(0); | ||
706 | } | ||
707 | } | ||
708 | |||
709 | if (child_pid > 0) { | ||
710 | child_pid = 0; | ||
711 | if (WIFEXITED(status)) { | ||
712 | int code = WEXITSTATUS(status); | ||
713 | if (code || verbose > 1) | ||
714 | error("child exited with status %d", | ||
715 | code); | ||
716 | } else if (WIFSIGNALED(status)) { | ||
717 | char const *coremsg = ""; | ||
718 | #ifdef WCOREDUMP | ||
719 | if (WCOREDUMP(status)) | ||
720 | coremsg = " (core dumped)"; | ||
721 | #endif | ||
722 | error("child terminated on signal %d%s", | ||
723 | WTERMSIG(status), coremsg); | ||
724 | } else if (WIFSTOPPED(status)) { | ||
725 | error("child stopped on signal %d", | ||
726 | WSTOPSIG(status)); | ||
727 | continue; | ||
728 | } else { | ||
729 | error("child terminated with unrecognized status %d", status); | ||
730 | } | ||
731 | /* restart the child */ | ||
732 | pid = 0; | ||
733 | continue; | ||
734 | } | ||
735 | |||
736 | switch (state) { | ||
737 | case RUNNING: | ||
738 | break; | ||
739 | |||
740 | case TERMINATING: | ||
741 | kill(pid, SIGTERM); | ||
742 | alarm(5); | ||
743 | state = CHILD_TERM; | ||
744 | break; | ||
745 | |||
746 | case CHILD_TERM: | ||
747 | break; | ||
748 | |||
749 | case CHILD_KILL: | ||
750 | kill(pid, SIGKILL); | ||
751 | return; | ||
752 | } | ||
753 | |||
754 | child_pid = wait(&status); | ||
755 | if (child_pid == -1) { | ||
756 | if (errno != EINTR || verbose > 1) | ||
757 | error("wait: %s", strerror(errno)); | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | |||
608 | int | 762 | int |
609 | main(int argc, char **argv) | 763 | main(int argc, char **argv) |
610 | { | 764 | { |
611 | int c, i; | 765 | int c, i; |
612 | int fd = -1; | 766 | int fd = -1; |
613 | struct MHD_Daemon *mhd; | ||
614 | struct sockaddr *server_addr; | 767 | struct sockaddr *server_addr; |
615 | int foreground = 0; | 768 | int foreground = 0; |
616 | sigset_t sigs; | 769 | int single_process = 0; |
617 | static int fatal_signals[] = { | ||
618 | SIGHUP, | ||
619 | SIGINT, | ||
620 | SIGQUIT, | ||
621 | SIGTERM, | ||
622 | 0 | ||
623 | }; | ||
624 | 770 | ||
625 | progname = basename(argv[0]); | 771 | progname = basename(argv[0]); |
626 | 772 | ||
@@ -629,7 +775,7 @@ main(int argc, char **argv) | |||
629 | if (!tmpdir) | 775 | if (!tmpdir) |
630 | tmpdir = "/tmp"; | 776 | tmpdir = "/tmp"; |
631 | 777 | ||
632 | while ((c = getopt(argc, argv, "c:fhv")) != EOF) { | 778 | while ((c = getopt(argc, argv, "c:fshv")) != EOF) { |
633 | switch (c) { | 779 | switch (c) { |
634 | case 'c': | 780 | case 'c': |
635 | config_file = optarg; | 781 | config_file = optarg; |
@@ -637,6 +783,9 @@ main(int argc, char **argv) | |||
637 | case 'f': | 783 | case 'f': |
638 | foreground = 1; | 784 | foreground = 1; |
639 | break; | 785 | break; |
786 | case 's': | ||
787 | single_process = 1; | ||
788 | break; | ||
640 | case 'h': | 789 | case 'h': |
641 | usage(); | 790 | usage(); |
642 | exit(0); | 791 | exit(0); |
@@ -649,7 +798,7 @@ main(int argc, char **argv) | |||
649 | } | 798 | } |
650 | 799 | ||
651 | readconfig(); | 800 | readconfig(); |
652 | 801 | ||
653 | pidfile_check(); | 802 | pidfile_check(); |
654 | 803 | ||
655 | if (mime_types_file) { | 804 | if (mime_types_file) { |
@@ -658,7 +807,8 @@ main(int argc, char **argv) | |||
658 |