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 66typedef enum {DO_NOTHING, SEND_SIGTERM, SEND_SIGKILL, GIVEUP} action_t; 67 68typedef struct extra_process_t { 69 struct extra_process_t *next; 70 pid_t pid; 71 ap_generation_t gen; 72} extra_process_t; 73 74static extra_process_t *extras; 75 76AP_DECLARE(void) ap_register_extra_mpm_process(pid_t pid, ap_generation_t gen) 77{ 78 extra_process_t *p = (extra_process_t *)ap_malloc(sizeof(extra_process_t)); 79 80 p->next = extras; 81 p->pid = pid; 82 p->gen = gen; 83 extras = p; 84} 85 86AP_DECLARE(int) ap_unregister_extra_mpm_process(pid_t pid, ap_generation_t *old_gen) 87{ 88 extra_process_t *cur = extras; 89 extra_process_t *prev = NULL; 90 91 while (cur && cur->pid != pid) { 92 prev = cur; 93 cur = cur->next; 94 } 95 96 if (cur) { 97 if (prev) { 98 prev->next = cur->next; 99 } 100 else { 101 extras = cur->next; 102 } 103 *old_gen = cur->gen; 104 free(cur); 105 return 1; /* found */ 106 } 107 else { 108 /* we don't know about any such process */ 109 return 0; 110 } 111} 112 113static int reclaim_one_pid(pid_t pid, action_t action) 114{ 115 apr_proc_t proc; 116 apr_status_t waitret; 117 apr_exit_why_e why; 118 int status; 119 120 /* Ensure pid sanity. */ 121 if (pid < 1) { 122 return 1; 123 } 124 125 proc.pid = pid; 126 waitret = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); 127 if (waitret != APR_CHILD_NOTDONE) { 128 if (waitret == APR_CHILD_DONE) 129 ap_process_child_status(&proc, why, status); 130 return 1; 131 } 132 133 switch(action) { 134 case DO_NOTHING: 135 break; 136 137 case SEND_SIGTERM: 138 /* ok, now it's being annoying */ 139 ap_log_error(APLOG_MARK, APLOG_WARNING, 140 0, ap_server_conf, APLOGNO(00045) 141 "child process %" APR_PID_T_FMT 142 " still did not exit, " 143 "sending a SIGTERM", 144 pid); 145 kill(pid, SIGTERM); 146 break; 147 148 case SEND_SIGKILL: 149 ap_log_error(APLOG_MARK, APLOG_ERR, 150 0, ap_server_conf, APLOGNO(00046) 151 "child process %" APR_PID_T_FMT 152 " still did not exit, " 153 "sending a SIGKILL", 154 pid); 155 kill(pid, SIGKILL); 156 break; 157 158 case GIVEUP: 159 /* gave it our best shot, but alas... If this really 160 * is a child we are trying to kill and it really hasn't 161 * exited, we will likely fail to bind to the port 162 * after the restart. 163 */ 164 ap_log_error(APLOG_MARK, APLOG_ERR, 165 0, ap_server_conf, APLOGNO(00047) 166 "could not make child process %" APR_PID_T_FMT 167 " exit, " 168 "attempting to continue anyway", 169 pid); 170 break; 171 } 172 173 return 0; 174} 175 176AP_DECLARE(void) ap_reclaim_child_processes(int terminate, 177 ap_reclaim_callback_fn_t *mpm_callback) 178{ 179 apr_time_t waittime = 1024 * 16; 180 int i; 181 extra_process_t *cur_extra; 182 int not_dead_yet; 183 int max_daemons; 184 apr_time_t starttime = apr_time_now(); 185 /* this table of actions and elapsed times tells what action is taken 186 * at which elapsed time from starting the reclaim 187 */ 188 struct { 189 action_t action; 190 apr_time_t action_time; 191 } action_table[] = { 192 {DO_NOTHING, 0}, /* dummy entry for iterations where we reap 193 * children but take no action against 194 * stragglers 195 */ 196 {SEND_SIGTERM, apr_time_from_sec(3)}, 197 {SEND_SIGTERM, apr_time_from_sec(5)}, 198 {SEND_SIGTERM, apr_time_from_sec(7)}, 199 {SEND_SIGKILL, apr_time_from_sec(9)}, 200 {GIVEUP, apr_time_from_sec(10)} 201 }; 202 int cur_action; /* index of action we decided to take this 203 * iteration 204 */ 205 int next_action = 1; /* index of first real action */ 206 207 ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons); 208 209 do { 210 apr_sleep(waittime); 211 /* don't let waittime get longer than 1 second; otherwise, we don't 212 * react quickly to the last child exiting, and taking action can 213 * be delayed 214 */ 215 waittime = waittime * 4; 216 if (waittime > apr_time_from_sec(1)) { 217 waittime = apr_time_from_sec(1); 218 } 219 220 /* see what action to take, if any */ 221 if (action_table[next_action].action_time <= apr_time_now() - starttime) { 222 cur_action = next_action; 223 ++next_action; 224 } 225 else { 226 cur_action = 0; /* nothing to do */ 227 } 228 229 /* now see who is done */ 230 not_dead_yet = 0; 231 for (i = 0; i < max_daemons; ++i) { 232 process_score *ps = ap_get_scoreboard_process(i); 233 pid_t pid = ps->pid; 234 235 if (pid == 0) { 236 continue; /* not every scoreboard entry is in use */ 237 } 238 239 if (reclaim_one_pid(pid, action_table[cur_action].action)) { 240 mpm_callback(i, 0, 0); 241 } 242 else { 243 ++not_dead_yet; 244 } 245 } 246 247 cur_extra = extras; 248 while (cur_extra) { 249 ap_generation_t old_gen; 250 extra_process_t *next = cur_extra->next; 251 252 if (reclaim_one_pid(cur_extra->pid, action_table[cur_action].action)) { 253 if (ap_unregister_extra_mpm_process(cur_extra->pid, &old_gen) == 1) { 254 mpm_callback(-1, cur_extra->pid, old_gen); 255 } 256 else { 257 AP_DEBUG_ASSERT(1 == 0); 258 } 259 } 260 else { 261 ++not_dead_yet; 262 } 263 cur_extra = next; 264 } 265#if APR_HAS_OTHER_CHILD 266 apr_proc_other_child_refresh_all(APR_OC_REASON_RESTART); 267#endif 268 269 } while (not_dead_yet > 0 && 270 action_table[cur_action].action != GIVEUP); 271} 272 273AP_DECLARE(void) ap_relieve_child_processes(ap_reclaim_callback_fn_t *mpm_callback) 274{ 275 int i; 276 extra_process_t *cur_extra; 277 int max_daemons; 278 279 ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons); 280 281 /* now see who is done */ 282 for (i = 0; i < max_daemons; ++i) { 283 process_score *ps = ap_get_scoreboard_process(i); 284 pid_t pid = ps->pid; 285 286 if (pid == 0) { 287 continue; /* not every scoreboard entry is in use */ 288 } 289 290 if (reclaim_one_pid(pid, DO_NOTHING)) { 291 mpm_callback(i, 0, 0); 292 } 293 } 294 295 cur_extra = extras; 296 while (cur_extra) { 297 ap_generation_t old_gen; 298 extra_process_t *next = cur_extra->next; 299 300 if (reclaim_one_pid(cur_extra->pid, DO_NOTHING)) { 301 if (ap_unregister_extra_mpm_process(cur_extra->pid, &old_gen) == 1) { 302 mpm_callback(-1, cur_extra->pid, old_gen); 303 } 304 else { 305 AP_DEBUG_ASSERT(1 == 0); 306 } 307 } 308 cur_extra = next; 309 } 310} 311 312/* Before sending the signal to the pid this function verifies that 313 * the pid is a member of the current process group; either using 314 * apr_proc_wait(), where waitpid() guarantees to fail for non-child 315 * processes; or by using getpgid() directly, if available. */ 316AP_DECLARE(apr_status_t) ap_mpm_safe_kill(pid_t pid, int sig) 317{ 318#ifndef HAVE_GETPGID 319 apr_proc_t proc; 320 apr_status_t rv; 321 apr_exit_why_e why; 322 int status; 323 324 /* Ensure pid sanity */ 325 if (pid < 1) { 326 return APR_EINVAL; 327 } 328 329 proc.pid = pid; 330 rv = apr_proc_wait(&proc, &status, &why, APR_NOWAIT); 331 if (rv == APR_CHILD_DONE) { 332 /* The child already died - log the termination status if 333 * necessary: */ 334 ap_process_child_status(&proc, why, status); 335 return APR_EINVAL; 336 } 337 else if (rv != APR_CHILD_NOTDONE) { 338 /* The child is already dead and reaped, or was a bogus pid - 339 * log this either way. */ 340 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, ap_server_conf, APLOGNO(00048) 341 "cannot send signal %d to pid %ld (non-child or " 342 "already dead)", sig, (long)pid); 343 return APR_EINVAL; 344 } 345#else 346 pid_t pg; 347 348 /* Ensure pid sanity. */ 349 if (pid < 1) { 350 return APR_EINVAL; 351 } 352 353 pg = getpgid(pid); 354 if (pg == -1) { 355 /* Process already dead... */ 356 return errno; 357 } 358 359 if (pg != getpgrp()) { 360 ap_log_error(APLOG_MARK, APLOG_ALERT, 0, ap_server_conf, APLOGNO(00049) 361 "refusing to send signal %d to pid %ld outside " 362 "process group", sig, (long)pid); 363 return APR_EINVAL; 364 } 365#endif 366 367 return kill(pid, sig) ? errno : APR_SUCCESS; 368} 369 370 371AP_DECLARE(int) ap_process_child_status(apr_proc_t *pid, apr_exit_why_e why, 372 int status) 373{ 374 int signum = status; 375 const char *sigdesc; 376 377 /* Child died... if it died due to a fatal error, 378 * we should simply bail out. The caller needs to 379 * check for bad rc from us and exit, running any 380 * appropriate cleanups. 381 * 382 * If the child died due to a resource shortage, 383 * the parent should limit the rate of forking 384 */ 385 if (APR_PROC_CHECK_EXIT(why)) { 386 if (status == APEXIT_CHILDSICK) { 387 return status; 388 } 389 390 if (status == APEXIT_CHILDFATAL) { 391 ap_log_error(APLOG_MARK, APLOG_ALERT, 392 0, ap_server_conf, APLOGNO(00050) 393 "Child %" APR_PID_T_FMT 394 " returned a Fatal error... Apache is exiting!", 395 pid->pid); 396 return APEXIT_CHILDFATAL; 397 } 398 399 return 0; 400 } 401 402 if (APR_PROC_CHECK_SIGNALED(why)) { 403 sigdesc = apr_signal_description_get(signum); 404 405 switch (signum) { 406 case SIGTERM: 407 case SIGHUP: 408 case AP_SIG_GRACEFUL: 409 case SIGKILL: 410 break; 411 412 default: 413 if (APR_PROC_CHECK_CORE_DUMP(why)) { 414 ap_log_error(APLOG_MARK, APLOG_NOTICE, 415 0, ap_server_conf, APLOGNO(00051) 416 "child pid %ld exit signal %s (%d), " 417 "possible coredump in %s", 418 (long)pid->pid, sigdesc, signum, 419 ap_coredump_dir); 420 } 421 else { 422 ap_log_error(APLOG_MARK, APLOG_NOTICE, 423 0, ap_server_conf, APLOGNO(00052) 424 "child pid %ld exit signal %s (%d)", 425 (long)pid->pid, sigdesc, signum); 426 } 427 } 428 } 429 return 0; 430} 431 432AP_DECLARE(apr_status_t) ap_mpm_pod_open(apr_pool_t *p, ap_pod_t **pod) 433{ 434 apr_status_t rv; 435 436 *pod = apr_palloc(p, sizeof(**pod)); 437 rv = apr_file_pipe_create_ex(&((*pod)->pod_in), &((*pod)->pod_out), 438 APR_WRITE_BLOCK, p); 439 if (rv != APR_SUCCESS) { 440 return rv; 441 } 442 443 apr_file_pipe_timeout_set((*pod)->pod_in, 0); 444 (*pod)->p = p; 445 446 /* close these before exec. */ 447 apr_file_inherit_unset((*pod)->pod_in); 448 apr_file_inherit_unset((*pod)->pod_out); 449 450 return APR_SUCCESS; 451} 452 453AP_DECLARE(apr_status_t) ap_mpm_pod_check(ap_pod_t *pod) 454{ 455 char c; 456 apr_size_t len = 1; 457 apr_status_t rv; 458 459 rv = apr_file_read(pod->pod_in, &c, &len); 460 461 if ((rv == APR_SUCCESS) && (len == 1)) { 462 return APR_SUCCESS; 463 } 464 465 if (rv != APR_SUCCESS) { 466 return rv; 467 } 468 469 return AP_NORESTART; 470} 471 472AP_DECLARE(apr_status_t) ap_mpm_pod_close(ap_pod_t *pod) 473{ 474 apr_status_t rv; 475 476 rv = apr_file_close(pod->pod_out); 477 if (rv != APR_SUCCESS) { 478 return rv; 479 } 480 481 rv = apr_file_close(pod->pod_in); 482 if (rv != APR_SUCCESS) { 483 return rv; 484 } 485 486 return APR_SUCCESS; 487} 488 489static apr_status_t pod_signal_internal(ap_pod_t *pod) 490{ 491 apr_status_t rv; 492 char char_of_death = '!'; 493 apr_size_t one = 1; 494 495 rv = apr_file_write(pod->pod_out, &char_of_death, &one); 496 if (rv != APR_SUCCESS) { 497 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00053) 498 "write pipe_of_death"); 499 } 500 501 return rv; 502} 503 504AP_DECLARE(apr_status_t) ap_mpm_podx_open(apr_pool_t *p, ap_pod_t **pod) 505{ 506 apr_status_t rv; 507 508 *pod = apr_palloc(p, sizeof(**pod)); 509 rv = apr_file_pipe_create(&((*pod)->pod_in), &((*pod)->pod_out), p); 510 if (rv != APR_SUCCESS) { 511 return rv; 512 } 513 /* 514 apr_file_pipe_timeout_set((*pod)->pod_in, 0); 515 */ 516 (*pod)->p = p; 517 518 /* close these before exec. */ 519 apr_file_inherit_unset((*pod)->pod_in); 520 apr_file_inherit_unset((*pod)->pod_out); 521 522 return APR_SUCCESS; 523} 524 525AP_DECLARE(int) ap_mpm_podx_check(ap_pod_t *pod) 526{ 527 char c; 528 apr_os_file_t fd; 529 int rc; 530 531 /* we need to surface EINTR so we'll have to grab the 532 * native file descriptor and do the OS read() ourselves 533 */ 534 apr_os_file_get(&fd, pod->pod_in); 535 rc = read(fd, &c, 1); 536 if (rc == 1) { 537 switch (c) { 538 case AP_MPM_PODX_RESTART_CHAR: 539 return AP_MPM_PODX_RESTART; 540 case AP_MPM_PODX_GRACEFUL_CHAR: 541 return AP_MPM_PODX_GRACEFUL; 542 } 543 } 544 return AP_MPM_PODX_NORESTART; 545} 546 547AP_DECLARE(apr_status_t) ap_mpm_podx_close(ap_pod_t *pod) 548{ 549 apr_status_t rv; 550 551 rv = apr_file_close(pod->pod_out); 552 if (rv != APR_SUCCESS) { 553 return rv; 554 } 555 556 rv = apr_file_close(pod->pod_in); 557 if (rv != APR_SUCCESS) { 558 return rv; 559 } 560 return rv; 561} 562 563static apr_status_t podx_signal_internal(ap_pod_t *pod, 564 ap_podx_restart_t graceful) 565{ 566 apr_status_t rv; 567 apr_size_t one = 1; 568 char char_of_death = ' '; 569 switch (graceful) { 570 case AP_MPM_PODX_RESTART: 571 char_of_death = AP_MPM_PODX_RESTART_CHAR; 572 break; 573 case AP_MPM_PODX_GRACEFUL: 574 char_of_death = AP_MPM_PODX_GRACEFUL_CHAR; 575 break; 576 case AP_MPM_PODX_NORESTART: 577 break; 578 } 579 580 rv = apr_file_write(pod->pod_out, &char_of_death, &one); 581 if (rv != APR_SUCCESS) { 582 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(2404) 583 "write pipe_of_death"); 584 } 585 return rv; 586} 587 588AP_DECLARE(apr_status_t) ap_mpm_podx_signal(ap_pod_t * pod, 589 ap_podx_restart_t graceful) 590{ 591 return podx_signal_internal(pod, graceful); 592} 593 594AP_DECLARE(void) ap_mpm_podx_killpg(ap_pod_t * pod, int num, 595 ap_podx_restart_t graceful) 596{ 597 int i; 598 apr_status_t rv = APR_SUCCESS; 599 600 for (i = 0; i < num && rv == APR_SUCCESS; i++) { 601 rv = podx_signal_internal(pod, graceful); 602 } 603} 604 605/* This function connects to the server and sends enough data to 606 * ensure the child wakes up and processes a new connection. This 607 * permits the MPM to skip the poll when there is only one listening 608 * socket, because it provides a alternate way to unblock an accept() 609 * when the pod is used. */ 610static apr_status_t dummy_connection(ap_pod_t *pod) 611{ 612 const char *data; 613 apr_status_t rv; 614 apr_socket_t *sock; 615 apr_pool_t *p; 616 apr_size_t len; 617 ap_listen_rec *lp; 618 619 /* create a temporary pool for the socket. pconf stays around too long */ 620 rv = apr_pool_create(&p, pod->p); 621 if (rv != APR_SUCCESS) { 622 return rv; 623 } 624 625 /* If possible, find a listener which is configured for 626 * plain-HTTP, not SSL; using an SSL port would either be 627 * expensive to do correctly (performing a complete SSL handshake) 628 * or cause log spam by doing incorrectly (simply sending EOF). */ 629 lp = ap_listeners; 630 while (lp && lp->protocol && strcasecmp(lp->protocol, "http") != 0) { 631 lp = lp->next; 632 } 633 if (!lp) { 634 lp = ap_listeners; 635 } 636 637 rv = apr_socket_create(&sock, lp->bind_addr->family, SOCK_STREAM, 0, p); 638 if (rv != APR_SUCCESS) { 639 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00054) 640 "get socket to connect to listener"); 641 apr_pool_destroy(p); 642 return rv; 643 } 644 645 /* on some platforms (e.g., FreeBSD), the kernel won't accept many 646 * queued connections before it starts blocking local connects... 647 * we need to keep from blocking too long and instead return an error, 648 * because the MPM won't want to hold up a graceful restart for a 649 * long time 650 */ 651 rv = apr_socket_timeout_set(sock, apr_time_from_sec(3)); 652 if (rv != APR_SUCCESS) { 653 ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00055) 654 "set timeout on socket to connect to listener"); 655 apr_socket_close(sock); 656 apr_pool_destroy(p); 657 return rv; 658 } 659 660 rv = apr_socket_connect(sock, lp->bind_addr); 661 if (rv != APR_SUCCESS) { 662 int log_level = APLOG_WARNING; 663 664 if (APR_STATUS_IS_TIMEUP(rv)) { 665 /* probably some server processes bailed out already and there 666 * is nobody around to call accept and clear out the kernel 667 * connection queue; usually this is not worth logging 668 */ 669 log_level = APLOG_DEBUG; 670 } 671 672 ap_log_error(APLOG_MARK, log_level, rv, ap_server_conf, APLOGNO(00056) 673 "connect to listener on %pI", lp->bind_addr); 674 apr_pool_destroy(p); 675 return rv; 676 } 677 678 if (lp->protocol && strcasecmp(lp->protocol, "https") == 0) { 679 /* Send a TLS 1.0 close_notify alert. This is perhaps the 680 * "least wrong" way to open and cleanly terminate an SSL 681 * connection. It should "work" without noisy error logs if 682 * the server actually expects SSLv3/TLSv1. With 683 * SSLv23_server_method() OpenSSL's SSL_accept() fails 684 * ungracefully on receipt of this message, since it requires 685 * an 11-byte ClientHello message and this is too short. */ 686 static const unsigned char tls10_close_notify[7] = { 687 '\x15', /* TLSPlainText.type = Alert (21) */ 688 '\x03', '\x01', /* TLSPlainText.version = {3, 1} */ 689 '\x00', '\x02', /* TLSPlainText.length = 2 */ 690 '\x01', /* Alert.level = warning (1) */ 691 '\x00' /* Alert.description = close_notify (0) */ 692 }; 693 data = (const char *)tls10_close_notify; 694 len = sizeof(tls10_close_notify); 695 } 696 else /* ... XXX other request types here? */ { 697 /* Create an HTTP request string. We include a User-Agent so 698 * that adminstrators can track down the cause of the 699 * odd-looking requests in their logs. A complete request is 700 * used since kernel-level filtering may require that much 701 * data before returning from accept(). */ 702 data = apr_pstrcat(p, "OPTIONS * HTTP/1.0\r\nUser-Agent: ", 703 ap_get_server_description(), 704 " (internal dummy connection)\r\n\r\n", NULL); 705 len = strlen(data); 706 } 707 708 apr_socket_send(sock, data, &len); 709 apr_socket_close(sock); 710 apr_pool_destroy(p); 711 712 return rv; 713} 714 715AP_DECLARE(apr_status_t) ap_mpm_pod_signal(ap_pod_t *pod) 716{ 717 apr_status_t rv; 718 719 rv = pod_signal_internal(pod); 720 if (rv != APR_SUCCESS) { 721 return rv; 722 } 723 724 return dummy_connection(pod); 725} 726 727void ap_mpm_pod_killpg(ap_pod_t *pod, int num) 728{ 729 int i; 730 apr_status_t rv = APR_SUCCESS; 731 732 /* we don't write anything to the pod here... we assume 733 * that the would-be reader of the pod has another way to 734 * see that it is time to die once we wake it up 735 * 736 * writing lots of things to the pod at once is very 737 * problematic... we can fill the kernel pipe buffer and 738 * be blocked until somebody consumes some bytes or 739 * we hit a timeout... if we hit a timeout we can't just 740 * keep trying because maybe we'll never successfully 741 * write again... but then maybe we'll leave would-be 742 * readers stranded (a number of them could be tied up for 743 * a while serving time-consuming requests) 744 */ 745 /* Recall: we only worry about IDLE child processes here */ 746 for (i = 0; i < num && rv == APR_SUCCESS; i++) { 747 if (ap_scoreboard_image->servers[i][0].status != SERVER_READY || 748 ap_scoreboard_image->servers[i][0].pid == 0) { 749 continue; 750 } 751 rv = dummy_connection(pod); 752 } 753} 754 755static const char *dash_k_arg = NULL; 756static const char *dash_k_arg_noarg = "noarg"; 757 758static int send_signal(pid_t pid, int sig) 759{ 760 if (kill(pid, sig) < 0) { 761 ap_log_error(APLOG_MARK, APLOG_STARTUP, errno, NULL, APLOGNO(00057) 762 "sending signal to server"); 763 return 1; 764 } 765 return 0; 766} 767 768int ap_signal_server(int *exit_status, apr_pool_t *pconf) 769{ 770 apr_status_t rv; 771 pid_t otherpid; 772 int running = 0; 773 const char *status; 774 775 *exit_status = 0; 776 777 rv = ap_read_pid(pconf, ap_pid_fname, &otherpid); 778 if (rv != APR_SUCCESS) { 779 if (!APR_STATUS_IS_ENOENT(rv)) { 780 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, NULL, APLOGNO(00058) 781 "Error retrieving pid file %s", ap_pid_fname); 782 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, APLOGNO(00059) 783 "Remove it before continuing if it is corrupted."); 784 *exit_status = 1; 785 return 1; 786 } 787 status = "httpd (no pid file) not running"; 788 } 789 else { 790 if (kill(otherpid, 0) == 0) { 791 running = 1; 792 status = apr_psprintf(pconf, 793 "httpd (pid %" APR_PID_T_FMT ") already " 794 "running", otherpid); 795 } 796 else { 797 status = apr_psprintf(pconf, 798 "httpd (pid %" APR_PID_T_FMT "?) not running", 799 otherpid); 800 } 801 } 802 803 if (!strcmp(dash_k_arg, "start") || dash_k_arg == dash_k_arg_noarg) { 804 if (running) { 805 printf("%s\n", status); 806 return 1; 807 } 808 } 809 810 if (!strcmp(dash_k_arg, "stop")) { 811 if (!running) { 812 printf("%s\n", status); 813 } 814 else { 815 send_signal(otherpid, SIGTERM); 816 } 817 return 1; 818 } 819 820 if (!strcmp(dash_k_arg, "restart")) { 821 if (!running) { 822 printf("httpd not running, trying to start\n"); 823 } 824 else { 825 *exit_status = send_signal(otherpid, SIGHUP); 826 return 1; 827 } 828 } 829 830 if (!strcmp(dash_k_arg, "graceful")) { 831 if (!running) { 832 printf("httpd not running, trying to start\n"); 833 } 834 else { 835 *exit_status = send_signal(otherpid, AP_SIG_GRACEFUL); 836 return 1; 837 } 838 } 839 840 if (!strcmp(dash_k_arg, "graceful-stop")) { 841 if (!running) { 842 printf("%s\n", status); 843 } 844 else { 845 *exit_status = send_signal(otherpid, AP_SIG_GRACEFUL_STOP); 846 } 847 return 1; 848 } 849 850 return 0; 851} 852 853void ap_mpm_rewrite_args(process_rec *process) 854{ 855 apr_array_header_t *mpm_new_argv; 856 apr_status_t rv; 857 apr_getopt_t *opt; 858 char optbuf[3]; 859 const char *optarg; 860 861 mpm_new_argv = apr_array_make(process->pool, process->argc, 862 sizeof(const char **)); 863 *(const char **)apr_array_push(mpm_new_argv) = process->argv[0]; 864 apr_getopt_init(&opt, process->pool, process->argc, process->argv); 865 opt->errfn = NULL; 866 optbuf[0] = '-'; 867 /* option char returned by apr_getopt() will be stored in optbuf[1] */ 868 optbuf[2] = '\0'; 869 while ((rv = apr_getopt(opt, "k:" AP_SERVER_BASEARGS, 870 optbuf + 1, &optarg)) == APR_SUCCESS) { 871 switch(optbuf[1]) { 872 case 'k': 873 if (!dash_k_arg) { 874 if (!strcmp(optarg, "start") || !strcmp(optarg, "stop") || 875 !strcmp(optarg, "restart") || !strcmp(optarg, "graceful") || 876 !strcmp(optarg, "graceful-stop")) { 877 dash_k_arg = optarg; 878 break; 879 } 880 } 881 default: 882 *(const char **)apr_array_push(mpm_new_argv) = 883 apr_pstrdup(process->pool, optbuf); 884 if (optarg) { 885 *(const char **)apr_array_push(mpm_new_argv) = optarg; 886 } 887 } 888 } 889 890 /* back up to capture the bad argument */ 891 if (rv == APR_BADCH || rv == APR_BADARG) { 892 opt->ind--; 893 } 894 895 while (opt->ind < opt->argc) { 896 *(const char **)apr_array_push(mpm_new_argv) = 897 apr_pstrdup(process->pool, opt->argv[opt->ind++]); 898 } 899 900 process->argc = mpm_new_argv->nelts; 901 process->argv = (const char * const *)mpm_new_argv->elts; 902 903 if (NULL == dash_k_arg) { 904 dash_k_arg = dash_k_arg_noarg; 905 } 906 907 APR_REGISTER_OPTIONAL_FN(ap_signal_server); 908} 909 910static pid_t parent_pid, my_pid; 911static apr_pool_t *pconf; 912 913#if AP_ENABLE_EXCEPTION_HOOK 914 915static int exception_hook_enabled; 916 917const char *ap_mpm_set_exception_hook(cmd_parms *cmd, void *dummy, 918 const char *arg) 919{ 920 const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); 921 if (err != NULL) { 922 return err; 923 } 924 925 if (cmd->server->is_virtual) { 926 return "EnableExceptionHook directive not allowed in <VirtualHost>"; 927 } 928 929 if (strcasecmp(arg, "on") == 0) { 930 exception_hook_enabled = 1; 931 } 932 else if (strcasecmp(arg, "off") == 0) { 933 exception_hook_enabled = 0; 934 } 935 else { 936 return "parameter must be 'on' or 'off'"; 937 } 938 939 return NULL; 940} 941 942static void run_fatal_exception_hook(int sig) 943{ 944 ap_exception_info_t ei = {0}; 945 946 if (exception_hook_enabled && 947 geteuid() != 0 && 948 my_pid != parent_pid) { 949 ei.sig = sig; 950 ei.pid = my_pid; 951 ap_run_fatal_exception(&ei); 952 } 953} 954#endif /* AP_ENABLE_EXCEPTION_HOOK */ 955 956/* handle all varieties of core dumping signals */ 957static void sig_coredump(int sig) 958{ 959 apr_filepath_set(ap_coredump_dir, pconf); 960 apr_signal(sig, SIG_DFL); 961#if AP_ENABLE_EXCEPTION_HOOK 962 run_fatal_exception_hook(sig); 963#endif 964 /* linuxthreads issue calling getpid() here: 965 * This comparison won't match if the crashing thread is 966 * some module's thread that runs in the parent process. 967 * The fallout, which is limited to linuxthreads: 968 * The special log message won't be written when such a 969 * thread in the parent causes the parent to crash. 970 */ 971 if (getpid() == parent_pid) { 972 ap_log_error(APLOG_MARK, APLOG_NOTICE, 973 0, ap_server_conf, APLOGNO(00060) 974 "seg fault or similar nasty error detected " 975 "in the parent process"); 976 /* XXX we can probably add some rudimentary cleanup code here, 977 * like getting rid of the pid file. If any additional bad stuff 978 * happens, we are protected from recursive errors taking down the 979 * system since this function is no longer the signal handler GLA 980 */ 981 } 982 kill(getpid(), sig); 983 /* At this point we've got sig blocked, because we're still inside 984 * the signal handler. When we leave the signal handler it will 985 * be unblocked, and we'll take the signal... and coredump or whatever 986 * is appropriate for this particular Unix. In addition the parent 987 * will see the real signal we received -- whereas if we called 988 * abort() here, the parent would only see SIGABRT. 989 */ 990} 991 992AP_DECLARE(apr_status_t) ap_fatal_signal_child_setup(server_rec *s) 993{ 994 my_pid = getpid(); 995 return APR_SUCCESS; 996} 997 998AP_DECLARE(apr_status_t) ap_fatal_signal_setup(server_rec *s, 999 apr_pool_t *in_pconf) 1000{ 1001#ifndef NO_USE_SIGACTION 1002 struct sigaction sa; 1003 1004 sigemptyset(&sa.sa_mask); 1005 1006#if defined(SA_ONESHOT) 1007 sa.sa_flags = SA_ONESHOT; 1008#elif defined(SA_RESETHAND) 1009 sa.sa_flags = SA_RESETHAND; 1010#else 1011 sa.sa_flags = 0; 1012#endif 1013 1014 sa.sa_handler = sig_coredump; 1015 if (sigaction(SIGSEGV, &sa, NULL) < 0) 1016 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00061) "sigaction(SIGSEGV)"); 1017#ifdef SIGBUS 1018 if (sigaction(SIGBUS, &sa, NULL) < 0) 1019 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00062) "sigaction(SIGBUS)"); 1020#endif 1021#ifdef SIGABORT 1022 if (sigaction(SIGABORT, &sa, NULL) < 0) 1023 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00063) "sigaction(SIGABORT)"); 1024#endif 1025#ifdef SIGABRT 1026 if (sigaction(SIGABRT, &sa, NULL) < 0) 1027 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00064) "sigaction(SIGABRT)"); 1028#endif 1029#ifdef SIGILL 1030 if (sigaction(SIGILL, &sa, NULL) < 0) 1031 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00065) "sigaction(SIGILL)"); 1032#endif 1033#ifdef SIGFPE 1034 if (sigaction(SIGFPE, &sa, NULL) < 0) 1035 ap_log_error(APLOG_MARK, APLOG_WARNING, errno, s, APLOGNO(00066) "sigaction(SIGFPE)"); 1036#endif 1037 1038#else /* NO_USE_SIGACTION */ 1039 1040 apr_signal(SIGSEGV, sig_coredump); 1041#ifdef SIGBUS 1042 apr_signal(SIGBUS, sig_coredump); 1043#endif /* SIGBUS */ 1044#ifdef SIGABORT 1045 apr_signal(SIGABORT, sig_coredump); 1046#endif /* SIGABORT */ 1047#ifdef SIGABRT 1048 apr_signal(SIGABRT, sig_coredump); 1049#endif /* SIGABRT */ 1050#ifdef SIGILL 1051 apr_signal(SIGILL, sig_coredump); 1052#endif /* SIGILL */ 1053#ifdef SIGFPE 1054 apr_signal(SIGFPE, sig_coredump); 1055#endif /* SIGFPE */ 1056 1057#endif /* NO_USE_SIGACTION */ 1058 1059 pconf = in_pconf; 1060 parent_pid = my_pid = getpid(); 1061 1062 return APR_SUCCESS; 1063} 1064 1065#endif /* WIN32 */ 1066