Apache HTTPD
mpm_unix.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* The purpose of this file is to store the code that MOST mpm's will need
18 * this does not mean a function only goes into this file if every MPM needs
19 * it. It means that if a function is needed by more than one MPM, and
20 * future maintenance would be served by making the code common, then the
21 * function belongs here.
22 *
23 * This is going in src/main because it is not platform specific, it is
24 * specific to multi-process servers, but NOT to Unix. Which is why it
25 * does not belong in src/os/unix
26 */
27
28#ifndef WIN32
29
30#include "apr.h"
31#include "apr_thread_proc.h"
32#include "apr_signal.h"
33#include "apr_strings.h"
34#define APR_WANT_STRFUNC
35#include "apr_want.h"
36#include "apr_getopt.h"
37#include "apr_optional.h"
38#include "apr_allocator.h"
39
40#include "httpd.h"
41#include "http_config.h"
42#include "http_core.h"
43#include "http_log.h"
44#include "http_main.h"
45#include "mpm_common.h"
46#include "ap_mpm.h"
47#include "ap_listen.h"
48#include "scoreboard.h"
49#include "util_mutex.h"
50
51#ifdef HAVE_PWD_H
52#include <pwd.h>
53#endif
54#ifdef HAVE_GRP_H
55#include <grp.h>
56#endif
57#if APR_HAVE_UNISTD_H
58#include <unistd.h>
59#endif
60
61
62/* we know core's module_index is 0 */
63#undef APLOG_MODULE_INDEX
64#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
65
73
79
81
83{
85
86 p->next = extras;
87 p->pid = pid;
88 p->gen = gen;
89 extras = p;
90}
91
93{
95 extra_process_t *prev = NULL;
96
97 while (cur && cur->pid != pid) {
98 prev = cur;
99 cur = cur->next;
100 }
101
102 if (cur) {
103 if (prev) {
104 prev->next = cur->next;
105 }
106 else {
107 extras = cur->next;
108 }
109 *old_gen = cur->gen;
110 free(cur);
111 return 1; /* found */
112 }
113 else {
114 /* we don't know about any such process */
115 return 0;
116 }
117}
118
120{
124 int status;
125
126 /* Ensure pid sanity. */
127 if (pid < 1) {
128 return 1;
129 }
130
131 proc.pid = pid;
133 if (waitret != APR_CHILD_NOTDONE) {
134 if (waitret == APR_CHILD_DONE)
136 return 1;
137 }
138
139 switch(action) {
140 case DO_NOTHING:
141 break;
142
143 case SEND_SIGTERM:
144 /* ok, now it's being annoying */
146 0, ap_server_conf, APLOGNO(00045)
147 "child process %" APR_PID_T_FMT
148 " still did not exit, "
149 "sending a SIGTERM",
150 pid);
151 /* FALLTHROUGH */
153 kill(pid, SIGTERM);
154 break;
155
156 case SEND_SIGKILL:
158 0, ap_server_conf, APLOGNO(00046)
159 "child process %" APR_PID_T_FMT
160 " still did not exit, "
161 "sending a SIGKILL",
162 pid);
163 kill(pid, SIGKILL);
164 break;
165
166 case GIVEUP:
167 /* gave it our best shot, but alas... If this really
168 * is a child we are trying to kill and it really hasn't
169 * exited, we will likely fail to bind to the port
170 * after the restart.
171 */
173 0, ap_server_conf, APLOGNO(00047)
174 "could not make child process %" APR_PID_T_FMT
175 " exit, "
176 "attempting to continue anyway",
177 pid);
178 break;
179 }
180
181 return 0;
182}
183
186{
187 apr_time_t waittime = 1024 * 16;
188 int i;
190 int not_dead_yet;
191 int max_daemons;
193 /* this table of actions and elapsed times tells what action is taken
194 * at which elapsed time from starting the reclaim
195 */
196 struct {
197 action_t action;
199 } action_table[] = {
200 {DO_NOTHING, 0}, /* dummy entry for iterations where we reap
201 * children but take no action against
202 * stragglers
203 */
204 {SEND_SIGTERM_NOLOG, 0}, /* skipped if terminate == 0 */
210 };
211 int cur_action; /* index of action we decided to take this
212 * iteration
213 */
214 int next_action = terminate ? 1 : 2; /* index of first real action */
215
217
218 do {
221 /* don't let waittime get longer than 1 second; otherwise, we don't
222 * react quickly to the last child exiting, and taking action can
223 * be delayed
224 */
225 waittime = waittime * 4;
226 if (waittime > apr_time_from_sec(1)) {
228 }
229 }
230
231 /* see what action to take, if any */
234 ++next_action;
235 }
236 else {
237 cur_action = 0; /* nothing to do */
238 }
239
240 /* now see who is done */
241 not_dead_yet = 0;
242 for (i = 0; i < max_daemons; ++i) {
244 pid_t pid = ps->pid;
245
246 if (pid == 0) {
247 continue; /* not every scoreboard entry is in use */
248 }
249
250 if (reclaim_one_pid(pid, action_table[cur_action].action)) {
251 mpm_callback(i, 0, 0);
252 }
253 else {
254 ++not_dead_yet;
255 }
256 }
257
259 while (cur_extra) {
262 pid_t pid = cur_extra->pid;
263
264 if (reclaim_one_pid(pid, action_table[cur_action].action)) {
266 /* cur_extra dangling pointer from here. */
267 mpm_callback(-1, pid, old_gen);
268 }
269 else {
270 AP_DEBUG_ASSERT(1 == 0);
271 }
272 }
273 else {
274 ++not_dead_yet;
275 }
276 cur_extra = next;
277 }
278#if APR_HAS_OTHER_CHILD
280#endif
281
282 } while (not_dead_yet > 0 &&
283 action_table[cur_action].action != GIVEUP);
284}
285
287{
288 int i;
290 int max_daemons;
291
293
294 /* now see who is done */
295 for (i = 0; i < max_daemons; ++i) {
297 pid_t pid = ps->pid;
298
299 if (pid == 0) {
300 continue; /* not every scoreboard entry is in use */
301 }
302
303 if (reclaim_one_pid(pid, DO_NOTHING)) {
304 mpm_callback(i, 0, 0);
305 }
306 }
307
309 while (cur_extra) {
312 pid_t pid = cur_extra->pid;
313
314 if (reclaim_one_pid(pid, DO_NOTHING)) {
316 /* cur_extra dangling pointer from here. */
317 mpm_callback(-1, pid, old_gen);
318 }
319 else {
320 AP_DEBUG_ASSERT(1 == 0);
321 }
322 }
323 cur_extra = next;
324 }
325}
326
327/* Before sending the signal to the pid this function verifies that
328 * the pid is a member of the current process group; either using
329 * apr_proc_wait(), where waitpid() guarantees to fail for non-child
330 * processes; or by using getpgid() directly, if available. */
332{
333#ifndef HAVE_GETPGID
335 apr_status_t rv;
337 int status;
338
339 /* Ensure pid sanity */
340 if (pid < 1) {
341 return APR_EINVAL;
342 }
343
344 proc.pid = pid;
346 if (rv == APR_CHILD_DONE) {
347 /* The child already died - log the termination status if
348 * necessary: */
350 return APR_EINVAL;
351 }
352 else if (rv != APR_CHILD_NOTDONE) {
353 /* The child is already dead and reaped, or was a bogus pid -
354 * log this either way. */
356 "cannot send signal %d to pid %ld (non-child or "
357 "already dead)", sig, (long)pid);
358 return APR_EINVAL;
359 }
360#else
361 pid_t pg;
362
363 /* Ensure pid sanity. */
364 if (pid < 1) {
365 return APR_EINVAL;
366 }
367
368 pg = getpgid(pid);
369 if (pg == -1) {
370 /* Process already dead... */
371 return errno;
372 }
373
374 if (pg != getpgrp()) {
376 "refusing to send signal %d to pid %ld outside "
377 "process group", sig, (long)pid);
378 return APR_EINVAL;
379 }
380#endif
381
382 return kill(pid, sig) ? errno : APR_SUCCESS;
383}
384
385
387 int status)
388{
389 int signum = status;
390 const char *sigdesc;
391
392 /* Child died... if it died due to a fatal error,
393 * we should simply bail out. The caller needs to
394 * check for bad rc from us and exit, running any
395 * appropriate cleanups.
396 *
397 * If the child died due to a resource shortage,
398 * the parent should limit the rate of forking
399 */
401 if (status == APEXIT_CHILDSICK) {
402 return status;
403 }
404
405 if (status == APEXIT_CHILDFATAL) {
407 0, ap_server_conf, APLOGNO(00050)
408 "Child %" APR_PID_T_FMT
409 " returned a Fatal error... Apache is exiting!",
410 pid->pid);
411 return APEXIT_CHILDFATAL;
412 }
413
414 return 0;
415 }
416
419
420 switch (signum) {
421 case SIGTERM:
422 case SIGHUP:
423 case AP_SIG_GRACEFUL:
424 case SIGKILL:
425 break;
426
427 default:
430 0, ap_server_conf, APLOGNO(00051)
431 "child pid %ld exit signal %s (%d), "
432 "possible coredump in %s",
433 (long)pid->pid, sigdesc, signum,
435 }
436 else {
438 0, ap_server_conf, APLOGNO(00052)
439 "child pid %ld exit signal %s (%d)",
440 (long)pid->pid, sigdesc, signum);
441 }
442 }
443 }
444 return 0;
445}
446
448{
449 apr_status_t rv;
450
451 *pod = apr_palloc(p, sizeof(**pod));
452 rv = apr_file_pipe_create_ex(&((*pod)->pod_in), &((*pod)->pod_out),
454 if (rv != APR_SUCCESS) {
455 return rv;
456 }
457
458 apr_file_pipe_timeout_set((*pod)->pod_in, 0);
459 (*pod)->p = p;
460
461 /* close these before exec. */
462 apr_file_inherit_unset((*pod)->pod_in);
463 apr_file_inherit_unset((*pod)->pod_out);
464
465 return APR_SUCCESS;
466}
467
469{
470 char c;
471 apr_size_t len = 1;
472 apr_status_t rv;
473
474 rv = apr_file_read(pod->pod_in, &c, &len);
475
476 if ((rv == APR_SUCCESS) && (len == 1)) {
477 return APR_SUCCESS;
478 }
479
480 if (rv != APR_SUCCESS) {
481 return rv;
482 }
483
484 return AP_NORESTART;
485}
486
488{
489 apr_status_t rv;
490
491 rv = apr_file_close(pod->pod_out);
492 if (rv != APR_SUCCESS) {
493 return rv;
494 }
495
496 rv = apr_file_close(pod->pod_in);
497 if (rv != APR_SUCCESS) {
498 return rv;
499 }
500
501 return APR_SUCCESS;
502}
503
505{
506 apr_status_t rv;
507 char char_of_death = '!';
508 apr_size_t one = 1;
509
511 if (rv != APR_SUCCESS) {
513 "write pipe_of_death");
514 }
515
516 return rv;
517}
518
520{
521 apr_status_t rv;
522
523 *pod = apr_palloc(p, sizeof(**pod));
524 rv = apr_file_pipe_create(&((*pod)->pod_in), &((*pod)->pod_out), p);
525 if (rv != APR_SUCCESS) {
526 return rv;
527 }
528 /*
529 apr_file_pipe_timeout_set((*pod)->pod_in, 0);
530 */
531 (*pod)->p = p;
532
533 /* close these before exec. */
534 apr_file_inherit_unset((*pod)->pod_in);
535 apr_file_inherit_unset((*pod)->pod_out);
536
537 return APR_SUCCESS;
538}
539
541{
542 char c;
544 int rc;
545
546 /* we need to surface EINTR so we'll have to grab the
547 * native file descriptor and do the OS read() ourselves
548 */
549 apr_os_file_get(&fd, pod->pod_in);
550 rc = read(fd, &c, 1);
551 if (rc == 1) {
552 switch (c) {
554 return AP_MPM_PODX_RESTART;
557 }
558 }
560}
561
563{
564 apr_status_t rv;
565
566 rv = apr_file_close(pod->pod_out);
567 if (rv != APR_SUCCESS) {
568 return rv;
569 }
570
571 rv = apr_file_close(pod->pod_in);
572 if (rv != APR_SUCCESS) {
573 return rv;
574 }
575 return rv;
576}
577
580{
581 apr_status_t rv;
582 apr_size_t one = 1;
583 char char_of_death = ' ';
584 switch (graceful) {
587 break;
590 break;
592 break;
593 }
594
596 if (rv != APR_SUCCESS) {
598 "write pipe_of_death");
599 }
600 return rv;
601}
602
608
611{
612 int i;
614
615 for (i = 0; i < num && rv == APR_SUCCESS; i++) {
617 }
618}
619
620/* This function connects to the server and sends enough data to
621 * ensure the child wakes up and processes a new connection. This
622 * permits the MPM to skip the poll when there is only one listening
623 * socket, because it provides a alternate way to unblock an accept()
624 * when the pod is used. */
626{
627 const char *data;
628 apr_status_t rv;
630 apr_pool_t *p;
633
634 /* create a temporary pool for the socket. pconf stays around too long */
635 rv = apr_pool_create(&p, pod->p);
636 if (rv != APR_SUCCESS) {
637 return rv;
638 }
639 apr_pool_tag(p, "dummy_connection");
640
641 /* If possible, find a listener which is configured for
642 * plain-HTTP, not SSL; using an SSL port would either be
643 * expensive to do correctly (performing a complete SSL handshake)
644 * or cause log spam by doing incorrectly (simply sending EOF). */
646 while (lp && lp->protocol && ap_cstr_casecmp(lp->protocol, "http") != 0) {
647 lp = lp->next;
648 }
649 if (!lp) {
651 }
652
653 rv = apr_socket_create(&sock, lp->bind_addr->family, SOCK_STREAM, 0, p);
654 if (rv != APR_SUCCESS) {
656 "get socket to connect to listener");
658 return rv;
659 }
660
661 /* on some platforms (e.g., FreeBSD), the kernel won't accept many
662 * queued connections before it starts blocking local connects...
663 * we need to keep from blocking too long and instead return an error,
664 * because the MPM won't want to hold up a graceful restart for a
665 * long time
666 */
668 if (rv != APR_SUCCESS) {
670 "set timeout on socket to connect to listener");
673 return rv;
674 }
675
676 rv = apr_socket_connect(sock, lp->bind_addr);
677 if (rv != APR_SUCCESS) {
679
680 if (APR_STATUS_IS_TIMEUP(rv)) {
681 /* probably some server processes bailed out already and there
682 * is nobody around to call accept and clear out the kernel
683 * connection queue; usually this is not worth logging
684 */
686 }
687
689 "connect to listener on %pI", lp->bind_addr);
691 return rv;
692 }
693
694 if (lp->protocol && ap_cstr_casecmp(lp->protocol, "https") == 0) {
695 /* Send a TLS 1.0 close_notify alert. This is perhaps the
696 * "least wrong" way to open and cleanly terminate an SSL
697 * connection. It should "work" without noisy error logs if
698 * the server actually expects SSLv3/TLSv1. With
699 * SSLv23_server_method() OpenSSL's SSL_accept() fails
700 * ungracefully on receipt of this message, since it requires
701 * an 11-byte ClientHello message and this is too short. */
702 static const unsigned char tls10_close_notify[7] = {
703 '\x15', /* TLSPlainText.type = Alert (21) */
704 '\x03', '\x01', /* TLSPlainText.version = {3, 1} */
705 '\x00', '\x02', /* TLSPlainText.length = 2 */
706 '\x01', /* Alert.level = warning (1) */
707 '\x00' /* Alert.description = close_notify (0) */
708 };
709 data = (const char *)tls10_close_notify;
710 len = sizeof(tls10_close_notify);
711 }
712 else /* ... XXX other request types here? */ {
713 /* Create an HTTP request string. We include a User-Agent so
714 * that administrators can track down the cause of the
715 * odd-looking requests in their logs. A complete request is
716 * used since kernel-level filtering may require that much
717 * data before returning from accept(). */
718 data = apr_pstrcat(p, "OPTIONS * HTTP/1.0\r\nUser-Agent: ",
720 " (internal dummy connection)\r\n\r\n", NULL);
721 len = strlen(data);
722 }
723
727
728 return rv;
729}
730
732{
733 apr_status_t rv;
734
735 rv = pod_signal_internal(pod);
736 if (rv != APR_SUCCESS) {
737 return rv;
738 }
739
740 return dummy_connection(pod);
741}
742
744{
745 int i;
747
748 /* we don't write anything to the pod here... we assume
749 * that the would-be reader of the pod has another way to
750 * see that it is time to die once we wake it up
751 *
752 * writing lots of things to the pod at once is very
753 * problematic... we can fill the kernel pipe buffer and
754 * be blocked until somebody consumes some bytes or
755 * we hit a timeout... if we hit a timeout we can't just
756 * keep trying because maybe we'll never successfully
757 * write again... but then maybe we'll leave would-be
758 * readers stranded (a number of them could be tied up for
759 * a while serving time-consuming requests)
760 */
761 /* Recall: we only worry about IDLE child processes here */
762 for (i = 0; i < num && rv == APR_SUCCESS; i++) {
764 ap_scoreboard_image->servers[i][0].pid == 0) {
765 continue;
766 }
767 rv = dummy_connection(pod);
768 }
769}
770
771static const char *dash_k_arg = NULL;
772static const char *dash_k_arg_noarg = "noarg";
773
774static int send_signal(pid_t pid, int sig)
775{
776 if (kill(pid, sig) < 0) {
778 "sending signal to server");
779 return 1;
780 }
781 return 0;
782}
783
785{
786 apr_status_t rv;
788 int running = 0;
789 const char *status;
790
791 *exit_status = 0;
792
794 if (rv != APR_SUCCESS) {
795 if (!APR_STATUS_IS_ENOENT(rv)) {
797 "Error retrieving pid file %s", ap_pid_fname);
799 "Remove it before continuing if it is corrupted.");
800 *exit_status = 1;
801 return 1;
802 }
803 status = "httpd (no pid file) not running";
804 }
805 else {
806 /* With containerization, httpd may get the same PID at each startup,
807 * handle it as if it were not running (it obviously can't).
808 */
809 if (otherpid != getpid() && kill(otherpid, 0) == 0) {
810 running = 1;
812 "httpd (pid %" APR_PID_T_FMT ") already "
813 "running", otherpid);
814 }
815 else {
817 "httpd (pid %" APR_PID_T_FMT "?) not running",
818 otherpid);
819 }
820 }
821
822 if (!strcmp(dash_k_arg, "start") || dash_k_arg == dash_k_arg_noarg) {
823 if (running) {
824 printf("%s\n", status);
825 return 1;
826 }
827 }
828
829 if (!strcmp(dash_k_arg, "stop")) {
830 if (!running) {
831 printf("%s\n", status);
832 }
833 else {
835 }
836 return 1;
837 }
838
839 if (!strcmp(dash_k_arg, "restart")) {
840 if (!running) {
841 printf("httpd not running, trying to start\n");
842 }
843 else {
845 return 1;
846 }
847 }
848
849 if (!strcmp(dash_k_arg, "graceful")) {
850 if (!running) {
851 printf("httpd not running, trying to start\n");
852 }
853 else {
855 return 1;
856 }
857 }
858
859 if (!strcmp(dash_k_arg, "graceful-stop")) {
860 if (!running) {
861 printf("%s\n", status);
862 }
863 else {
865 }
866 return 1;
867 }
868
869 return 0;
870}
871
873{
875 apr_status_t rv;
877 char optbuf[3];
878 const char *optarg;
879
880 mpm_new_argv = apr_array_make(process->pool, process->argc,
881 sizeof(const char **));
882 *(const char **)apr_array_push(mpm_new_argv) = process->argv[0];
883 apr_getopt_init(&opt, process->pool, process->argc, process->argv);
884 opt->errfn = NULL;
885 optbuf[0] = '-';
886 /* option char returned by apr_getopt() will be stored in optbuf[1] */
887 optbuf[2] = '\0';
888 while ((rv = apr_getopt(opt, "k:" AP_SERVER_BASEARGS,
889 optbuf + 1, &optarg)) == APR_SUCCESS) {
890 switch(optbuf[1]) {
891 case 'k':
892 if (!dash_k_arg) {
893 if (!strcmp(optarg, "start") || !strcmp(optarg, "stop") ||
894 !strcmp(optarg, "restart") || !strcmp(optarg, "graceful") ||
895 !strcmp(optarg, "graceful-stop")) {
897 break;
898 }
899 }
900 default:
901 *(const char **)apr_array_push(mpm_new_argv) =
902 apr_pstrdup(process->pool, optbuf);
903 if (optarg) {
904 *(const char **)apr_array_push(mpm_new_argv) = optarg;
905 }
906 }
907 }
908
909 /* back up to capture the bad argument */
910 if (rv == APR_BADCH || rv == APR_BADARG) {
911 opt->ind--;
912 }
913
914 while (opt->ind < opt->argc) {
915 *(const char **)apr_array_push(mpm_new_argv) =
916 apr_pstrdup(process->pool, opt->argv[opt->ind++]);
917 }
918
919 process->argc = mpm_new_argv->nelts;
920 process->argv = (const char * const *)mpm_new_argv->elts;
921
922 if (NULL == dash_k_arg) {
924 }
925
927}
928
931
932#if AP_ENABLE_EXCEPTION_HOOK
933
934static int exception_hook_enabled;
935
936const char *ap_mpm_set_exception_hook(cmd_parms *cmd, void *dummy,
937 const char *arg)
938{
939 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
940 if (err != NULL) {
941 return err;
942 }
943
944 if (cmd->server->is_virtual) {
945 return "EnableExceptionHook directive not allowed in <VirtualHost>";
946 }
947
948 if (strcasecmp(arg, "on") == 0) {
950 }
951 else if (strcasecmp(arg, "off") == 0) {
953 }
954 else {
955 return "parameter must be 'on' or 'off'";
956 }
957
958 return NULL;
959}
960
961static void run_fatal_exception_hook(int sig)
962{
964
966 geteuid() != 0 &&
967 my_pid != parent_pid) {
968 ei.sig = sig;
969 ei.pid = my_pid;
971 }
972}
973#endif /* AP_ENABLE_EXCEPTION_HOOK */
974
975/* handle all varieties of core dumping signals */
976static void sig_coredump(int sig)
977{
980#if AP_ENABLE_EXCEPTION_HOOK
982#endif
983 /* linuxthreads issue calling getpid() here:
984 * This comparison won't match if the crashing thread is
985 * some module's thread that runs in the parent process.
986 * The fallout, which is limited to linuxthreads:
987 * The special log message won't be written when such a
988 * thread in the parent causes the parent to crash.
989 */
990 if (getpid() == parent_pid) {
992 0, ap_server_conf, APLOGNO(00060)
993 "seg fault or similar nasty error detected "
994 "in the parent process");
995 /* XXX we can probably add some rudimentary cleanup code here,
996 * like getting rid of the pid file. If any additional bad stuff
997 * happens, we are protected from recursive errors taking down the
998 * system since this function is no longer the signal handler GLA
999 */
1000 }
1001 kill(getpid(), sig);
1002 /* At this point we've got sig blocked, because we're still inside
1003 * the signal handler. When we leave the signal handler it will
1004 * be unblocked, and we'll take the signal... and coredump or whatever
1005 * is appropriate for this particular Unix. In addition the parent
1006 * will see the real signal we received -- whereas if we called
1007 * abort() here, the parent would only see SIGABRT.
1008 */
1009}
1010
1016
1017/* We can't call sig_coredump (ap_log_error) once pconf is destroyed, so
1018 * avoid double faults by restoring each default signal handler on cleanup.
1019 */
1021{
1022 (void)unused;
1023
1025#ifdef SIGBUS
1027#endif /* SIGBUS */
1028#ifdef SIGABORT
1030#endif /* SIGABORT */
1031#ifdef SIGABRT
1033#endif /* SIGABRT */
1034#ifdef SIGILL
1036#endif /* SIGILL */
1037#ifdef SIGFPE
1039#endif /* SIGFPE */
1040
1041 return APR_SUCCESS;
1042}
1043
1046{
1047#ifndef NO_USE_SIGACTION
1048 struct sigaction sa;
1049
1050 memset(&sa, 0, sizeof sa);
1051 sigemptyset(&sa.sa_mask);
1052
1053#if defined(SA_ONESHOT)
1054 sa.sa_flags = SA_ONESHOT;
1055#elif defined(SA_RESETHAND)
1056 sa.sa_flags = SA_RESETHAND;
1057#endif
1058
1059 sa.sa_handler = sig_coredump;
1060 if (sigaction(SIGSEGV, &sa, NULL) < 0)
1061 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00061) "sigaction(SIGSEGV)");
1062#ifdef SIGBUS
1063 if (sigaction(SIGBUS, &sa, NULL) < 0)
1064 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00062) "sigaction(SIGBUS)");
1065#endif
1066#ifdef SIGABORT
1067 if (sigaction(SIGABORT, &sa, NULL) < 0)
1068 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00063) "sigaction(SIGABORT)");
1069#endif
1070#ifdef SIGABRT
1071 if (sigaction(SIGABRT, &sa, NULL) < 0)
1072 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00064) "sigaction(SIGABRT)");
1073#endif
1074#ifdef SIGILL
1075 if (sigaction(SIGILL, &sa, NULL) < 0)
1076 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00065) "sigaction(SIGILL)");
1077#endif
1078#ifdef SIGFPE
1079 if (sigaction(SIGFPE, &sa, NULL) < 0)
1080 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00066) "sigaction(SIGFPE)");
1081#endif
1082
1083#else /* NO_USE_SIGACTION */
1084
1086#ifdef SIGBUS
1088#endif /* SIGBUS */
1089#ifdef SIGABORT
1091#endif /* SIGABORT */
1092#ifdef SIGABRT
1094#endif /* SIGABRT */
1095#ifdef SIGILL
1097#endif /* SIGILL */
1098#ifdef SIGFPE
1100#endif /* SIGFPE */
1101
1102#endif /* NO_USE_SIGACTION */
1103
1104 pconf = in_pconf;
1105 parent_pid = my_pid = getpid();
1108
1109 return APR_SUCCESS;
1110}
1111
1112#endif /* WIN32 */
#define AP_DECLARE(type)
Definition ap_config.h:67
Apache Listeners Library.
Apache Multi-Processing Module library.
const char apr_size_t len
Definition ap_regex.h:187
APR Internal Memory Allocation.
APR Command Arguments (getopt)
APR-UTIL registration of functions exported by modules.
APR Signal Handling.
APR Strings library.
APR Thread and Process Library.
APR Standard Headers Support.
const char server_rec server_rec ** ps
const char * ap_get_server_description(void)
Definition core.c:3587
#define APEXIT_CHILDSICK
Definition httpd.h:335
#define APEXIT_CHILDFATAL
Definition httpd.h:341
ap_listen_rec * ap_listeners
Definition listen.c:42
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_NOTICE
Definition http_log.h:69
#define APLOG_STARTUP
Definition http_log.h:105
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
apr_status_t ap_read_pid(apr_pool_t *p, const char *filename, pid_t *mypid)
Definition log.c:1697
#define APLOG_MARK
Definition http_log.h:283
#define APLOG_WARNING
Definition http_log.h:68
#define APLOG_ALERT
Definition http_log.h:65
#define APLOG_DEBUG
Definition http_log.h:71
#define AP_SERVER_BASEARGS
Definition http_main.h:36
server_rec * ap_server_conf
Definition config.c:62
void * dummy
Definition http_vhost.h:62
void const char * arg
Definition http_vhost.h:63
#define AP_MPM_PODX_GRACEFUL_CHAR
Definition mpm_common.h:282
const char * ap_pid_fname
Definition mpm_common.c:150
char ap_coredump_dir[8192]
Definition mpm_common.c:152
void ap_mpm_rewrite_args(process_rec *process)
Definition mpm_unix.c:872
#define AP_SIG_GRACEFUL_STOP
Definition mpm_common.h:76
apr_status_t ap_mpm_safe_kill(pid_t pid, int sig)
Definition mpm_unix.c:331
apr_status_t ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod)
Definition mpm_unix.c:447
apr_status_t ap_mpm_pod_close(ap_pod_t *pod)
Definition mpm_unix.c:487
apr_status_t ap_mpm_pod_signal(ap_pod_t *pod)
Definition mpm_unix.c:731
int ap_unregister_extra_mpm_process(pid_t pid, ap_generation_t *old_gen)
Definition mpm_unix.c:92
int ap_signal_server(int *exit_status, apr_pool_t *pconf)
Definition mpm_unix.c:784
void ap_relieve_child_processes(ap_reclaim_callback_fn_t *mpm_callback)
Definition mpm_unix.c:286
int ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, int status)
Definition mpm_unix.c:386
void ap_reclaim_child_processes(int terminate, ap_reclaim_callback_fn_t *mpm_callback)
Definition mpm_unix.c:184
apr_status_t ap_fatal_signal_child_setup(server_rec *s)
Definition mpm_unix.c:1011
#define AP_MPM_PODX_RESTART_CHAR
Definition mpm_common.h:281
void ap_mpm_pod_killpg(ap_pod_t *pod, int num)
Definition mpm_unix.c:743
void ap_reclaim_callback_fn_t(int childnum, pid_t pid, ap_generation_t gen)
Definition mpm_common.h:89
void ap_mpm_podx_killpg(ap_pod_t *pod, int num, ap_podx_restart_t graceful)
Definition mpm_unix.c:609
void ap_register_extra_mpm_process(pid_t pid, ap_generation_t gen)
Definition mpm_unix.c:82
apr_status_t ap_fatal_signal_setup(server_rec *s, apr_pool_t *in_pconf)
Definition mpm_unix.c:1044
int ap_mpm_podx_check(ap_pod_t *pod)
Definition mpm_unix.c:540
#define AP_SIG_GRACEFUL
Definition mpm_common.h:67
apr_status_t ap_mpm_podx_signal(ap_pod_t *pod, ap_podx_restart_t graceful)
Definition mpm_unix.c:603
apr_status_t ap_mpm_podx_close(ap_pod_t *pod)
Definition mpm_unix.c:562
ap_podx_restart_t
Definition mpm_common.h:284
apr_status_t ap_mpm_pod_check(ap_pod_t *pod)
Definition mpm_unix.c:468
apr_status_t ap_mpm_podx_open(apr_pool_t *p, ap_pod_t **pod)
Definition mpm_unix.c:519
@ AP_MPM_PODX_NORESTART
Definition mpm_common.h:284
@ AP_MPM_PODX_RESTART
Definition mpm_common.h:284
@ AP_MPM_PODX_GRACEFUL
Definition mpm_common.h:284
#define APR_CHILD_NOTDONE
Definition apr_errno.h:448
#define APR_CHILD_DONE
Definition apr_errno.h:446
#define APR_BADCH
Definition apr_errno.h:457
#define APR_BADARG
Definition apr_errno.h:459
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_OC_REASON_RESTART
#define APR_STATUS_IS_TIMEUP(s)
Definition apr_errno.h:534
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_file_t * fd
#define APR_REGISTER_OPTIONAL_FN(name)
apr_redis_t * rc
Definition apr_redis.h:173
int ap_cstr_casecmp(const char *s1, const char *s2)
Definition util.c:3542
#define AP_NORESTART
Definition httpd.h:2519
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
void * ap_malloc(size_t size) __attribute__((malloc))
Definition util.c:3152
#define GLOBAL_ONLY
const char * ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden)
Definition core.c:1301
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
void * data
int strcasecmp(const char *a, const char *b)
apr_vformatter_buff_t * c
Definition apr_lib.h:175
apr_int32_t opt
apr_socket_t * sock
apr_sockaddr_t * sa
apr_interval_time_t apr_int32_t * num
Definition apr_poll.h:273
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
int apr_os_file_t
#define apr_signal(a, b)
Definition apr_signal.h:71
const char * s
Definition apr_strings.h:95
apr_proc_t * proc
apr_int32_t apr_int32_t apr_int32_t err
#define APR_PROC_CHECK_CORE_DUMP(x)
#define APR_WRITE_BLOCK
#define APR_PROC_CHECK_EXIT(x)
int sig
apr_cmdtype_e cmd
#define APR_PROC_CHECK_SIGNALED(x)
apr_exit_why_e
int int status
@ APR_NOWAIT
apr_int64_t apr_time_t
Definition apr_time.h:45
#define apr_time_from_sec(sec)
Definition apr_time.h:78
apr_status_t ap_mpm_query(int query_code, int *result)
Definition mpm_common.c:421
#define AP_MPMQ_MAX_DAEMON_USED
Definition ap_mpm.h:150
Apache Configuration.
CORE HTTP Daemon.
Apache Logging library.
Command line options.
HTTP Daemon routines.
apr_pool_t * p
Definition md_event.c:32
static md_log_level_cb * log_level
Definition md_log.c:50
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
Multi-Processing Modules functions.
static const char * dash_k_arg
Definition mpm_unix.c:771
static apr_status_t pod_signal_internal(ap_pod_t *pod)
Definition mpm_unix.c:504
static apr_status_t fatal_signal_cleanup(void *unused)
Definition mpm_unix.c:1020
static const char * dash_k_arg_noarg
Definition mpm_unix.c:772
static int send_signal(pid_t pid, int sig)
Definition mpm_unix.c:774
static void sig_coredump(int sig)
Definition mpm_unix.c:976
static apr_pool_t * pconf
Definition mpm_unix.c:930
static apr_status_t podx_signal_internal(ap_pod_t *pod, ap_podx_restart_t graceful)
Definition mpm_unix.c:578
static pid_t parent_pid
Definition mpm_unix.c:929
static extra_process_t * extras
Definition mpm_unix.c:80
static apr_status_t dummy_connection(ap_pod_t *pod)
Definition mpm_unix.c:625
static int reclaim_one_pid(pid_t pid, action_t action)
Definition mpm_unix.c:119
action_t
Definition mpm_unix.c:66
@ SEND_SIGKILL
Definition mpm_unix.c:70
@ SEND_SIGTERM
Definition mpm_unix.c:68
@ DO_NOTHING
Definition mpm_unix.c:67
@ SEND_SIGTERM_NOLOG
Definition mpm_unix.c:69
@ GIVEUP
Definition mpm_unix.c:71
static pid_t my_pid
Definition mpm_unix.c:929
const char * apr_signal_description_get(int signum)
Definition signals.c:38
Apache scoreboard library.
int ap_generation_t
Definition scoreboard.h:78
scoreboard * ap_scoreboard_image
Definition scoreboard.c:44
#define SERVER_READY
Definition scoreboard.h:58
process_score * ap_get_scoreboard_process(int x)
Definition scoreboard.c:702
apr_array_header_t * mpm_new_argv
Apache's listeners record.
Definition ap_listen.h:47
ap_listen_rec * next
Definition ap_listen.h:51
apr_file_t * pod_in
Definition mpm_common.h:241
apr_pool_t * p
Definition mpm_common.h:243
apr_file_t * pod_out
Definition mpm_common.h:242
ap_generation_t gen
Definition mpm_unix.c:77
struct extra_process_t * next
Definition mpm_unix.c:75
A structure that represents one process.
Definition httpd.h:829
int argc
Definition httpd.h:839
apr_pool_t * pool
Definition httpd.h:831
const char *const * argv
Definition httpd.h:837
worker_score ** servers
Definition scoreboard.h:163
A structure to store information for each virtual server.
Definition httpd.h:1322
unsigned char status
Definition scoreboard.h:102
apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len)
Definition sendrecv.c:30
apr_status_t apr_socket_close(apr_socket_t *thesocket)
Definition sockets.c:211
apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa)
Definition sockets.c:388
apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, int protocol, apr_pool_t *cont)
Definition sockets.c:116
apr_status_t apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
Definition sockopt.c:75
Apache Mutex support library.