summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-04-20 11:35:45 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-04-20 12:18:41 +0300
commit44a3ae866bf949b0ca5106ecfb8c5e3fda4b9af8 (patch)
tree5eb53b9505aba56a58848faf15ea7c2b996f7fb0
parente8caefcc1b1a19abfca6a1e0a7dfea4af2761b53 (diff)
downloadfileserv-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.c206
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
609static int fatal_signals[] = {
610 SIGHUP,
611 SIGINT,
612 SIGQUIT,
613 SIGTERM,
614 0
615};
616
617static void
618http_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
649enum 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};
655volatile enum state state;
656
657static void
658sigterm(int sig)
659{
660 if (state == RUNNING)
661 state = TERMINATING;
662}
663
664static void
665sigalrm(int sig)
666{
667 if (state == CHILD_TERM)
668 state = CHILD_KILL;
669}
670
671static void
672http_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
608int 762int
609main(int argc, char **argv) 763main(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