1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_main.h> 8 9 #if (NXT_HAVE_CLONE) 10 #include <nxt_clone.h> 11 #endif 12 13 #include <signal.h> 14 15 #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 16 #include <sys/prctl.h> 17 #endif 18 19 20 #if (NXT_HAVE_CLONE) && (NXT_HAVE_CLONE_NEWPID) 21 #define nxt_is_pid_isolated(process) \ 22 nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID) 23 #else 24 #define nxt_is_pid_isolated(process) \ 25 (0) 26 #endif 27 28 29 static nxt_pid_t nxt_process_create(nxt_task_t *task, nxt_process_t *process); 30 static nxt_int_t nxt_process_do_start(nxt_task_t *task, nxt_process_t *process); 31 static nxt_int_t nxt_process_whoami(nxt_task_t *task, nxt_process_t *process); 32 static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process); 33 static nxt_int_t nxt_process_child_fixup(nxt_task_t *task, 34 nxt_process_t *process); 35 static void nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, 36 void *data); 37 static void nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 38 void *data); 39 static nxt_int_t nxt_process_send_created(nxt_task_t *task, 40 nxt_process_t *process); 41 static nxt_int_t nxt_process_send_ready(nxt_task_t *task, 42 nxt_process_t *process); 43 static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, 44 void *data); 45 static void nxt_process_created_error(nxt_task_t *task, 46 nxt_port_recv_msg_t *msg, void *data); 47 48 49 /* A cached process pid. */ 50 nxt_pid_t nxt_pid; 51 52 /* An original parent process pid. */ 53 nxt_pid_t nxt_ppid; 54 55 /* A cached process effective uid */ 56 nxt_uid_t nxt_euid; 57 58 /* A cached process effective gid */ 59 nxt_gid_t nxt_egid; 60 61 uint8_t nxt_proc_keep_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { 62 { 1, 1, 1, 1, 1, 1 }, 63 { 1, 0, 0, 0, 0, 0 }, 64 { 1, 0, 0, 1, 0, 0 }, 65 { 1, 0, 1, 1, 1, 1 }, 66 { 1, 0, 0, 1, 0, 0 }, 67 { 1, 0, 0, 1, 0, 0 }, 68 }; 69 70 uint8_t nxt_proc_send_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { 71 { 1, 1, 1, 1, 1, 1 }, 72 { 1, 0, 0, 0, 0, 0 }, 73 { 1, 0, 0, 1, 0, 0 }, 74 { 1, 0, 1, 1, 1, 1 }, 75 { 1, 0, 0, 0, 0, 0 }, 76 { 1, 0, 0, 0, 0, 0 }, 77 }; 78 79 uint8_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = { 80 { 0, 0, 0, 0, 0, 0 }, 81 { 0, 0, 0, 0, 0, 0 }, 82 { 0, 0, 0, 1, 0, 0 }, 83 { 0, 0, 1, 0, 1, 1 }, 84 { 0, 0, 0, 1, 0, 0 }, 85 { 1, 0, 0, 1, 0, 0 }, 86 }; 87 88 89 static const nxt_port_handlers_t nxt_process_whoami_port_handlers = { 90 .quit = nxt_signal_quit_handler, 91 .rpc_ready = nxt_port_rpc_handler, 92 .rpc_error = nxt_port_rpc_handler, 93 }; 94 95 96 nxt_process_t * 97 nxt_process_new(nxt_runtime_t *rt) 98 { 99 nxt_process_t *process; 100 101 process = nxt_mp_zalloc(rt->mem_pool, sizeof(nxt_process_t) 102 + sizeof(nxt_process_init_t)); 103 104 if (nxt_slow_path(process == NULL)) { 105 return NULL; 106 } 107 108 nxt_queue_init(&process->ports); 109 110 nxt_thread_mutex_create(&process->incoming.mutex); 111 112 process->use_count = 1; 113 114 nxt_queue_init(&process->children); 115 116 return process; 117 } 118 119 120 void 121 nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i) 122 { 123 process->use_count += i; 124 125 if (process->use_count == 0) { 126 nxt_runtime_process_release(task->thread->runtime, process); 127 } 128 } 129 130 131 nxt_int_t 132 nxt_process_init_start(nxt_task_t *task, nxt_process_init_t init) 133 { 134 nxt_int_t ret; 135 nxt_runtime_t *rt; 136 nxt_process_t *process; 137 nxt_process_init_t *pinit; 138 139 rt = task->thread->runtime; 140 141 process = nxt_process_new(rt); 142 if (nxt_slow_path(process == NULL)) { 143 return NXT_ERROR; 144 } 145 146 process->parent_port = rt->port_by_type[rt->type]; 147 148 process->name = init.name; 149 process->user_cred = &rt->user_cred; 150 151 pinit = nxt_process_init(process); 152 *pinit = init; 153 154 ret = nxt_process_start(task, process); 155 if (nxt_slow_path(ret == NXT_ERROR)) { 156 nxt_process_use(task, process, -1); 157 } 158 159 return ret; 160 } 161 162 163 nxt_int_t 164 nxt_process_start(nxt_task_t *task, nxt_process_t *process) 165 { 166 nxt_mp_t *tmp_mp; 167 nxt_int_t ret; 168 nxt_pid_t pid; 169 nxt_port_t *port; 170 nxt_process_init_t *init; 171 172 init = nxt_process_init(process); 173 174 port = nxt_port_new(task, 0, 0, init->type); 175 if (nxt_slow_path(port == NULL)) { 176 return NXT_ERROR; 177 } 178 179 nxt_process_port_add(task, process, port); 180 181 ret = nxt_port_socket_init(task, port, 0); 182 if (nxt_slow_path(ret != NXT_OK)) { 183 goto free_port; 184 } 185 186 tmp_mp = nxt_mp_create(1024, 128, 256, 32); 187 if (nxt_slow_path(tmp_mp == NULL)) { 188 ret = NXT_ERROR; 189 190 goto close_port; 191 } 192 193 if (init->prefork) { 194 ret = init->prefork(task, process, tmp_mp); 195 if (nxt_slow_path(ret != NXT_OK)) { 196 goto free_mempool; 197 } 198 } 199 200 pid = nxt_process_create(task, process); 201 202 switch (pid) { 203 204 case -1: 205 ret = NXT_ERROR; 206 break; 207 208 case 0: 209 /* The child process: return to the event engine work queue loop. */ 210 211 nxt_process_use(task, process, -1); 212 213 ret = NXT_AGAIN; 214 break; 215 216 default: 217 /* The parent process created a new process. */ 218 219 nxt_process_use(task, process, -1); 220 221 nxt_port_read_close(port); 222 nxt_port_write_enable(task, port); 223 224 ret = NXT_OK; 225 break; 226 } 227 228 free_mempool: 229 230 nxt_mp_destroy(tmp_mp); 231 232 close_port: 233 234 if (nxt_slow_path(ret == NXT_ERROR)) { 235 nxt_port_close(task, port); 236 } 237 238 free_port: 239 240 nxt_port_use(task, port, -1); 241 242 return ret; 243 } 244 245 246 static nxt_int_t 247 nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process) 248 { 249 nxt_process_t *p; 250 nxt_runtime_t *rt; 251 nxt_process_init_t *init; 252 nxt_process_type_t ptype; 253 254 init = nxt_process_init(process); 255 256 nxt_ppid = nxt_pid; 257 258 nxt_pid = nxt_getpid(); 259 260 process->pid = nxt_pid; 261 process->isolated_pid = nxt_pid; 262 263 /* Clean inherited cached thread tid. */ 264 task->thread->tid = 0; 265 266 ptype = init->type; 267 268 nxt_port_reset_next_id(); 269 270 nxt_event_engine_thread_adopt(task->thread->engine); 271 272 rt = task->thread->runtime; 273 274 /* Remove not ready processes. */ 275 nxt_runtime_process_each(rt, p) { 276 277 if (nxt_proc_keep_matrix[ptype][nxt_process_type(p)] == 0 278 && p->pid != nxt_ppid) /* Always keep parent's port. */ 279 { 280 nxt_debug(task, "remove not required process %PI", p->pid); 281 282 nxt_process_close_ports(task, p); 283 284 continue; 285 } 286 287 if (p->state != NXT_PROCESS_STATE_READY) { 288 nxt_debug(task, "remove not ready process %PI", p->pid); 289 290 nxt_process_close_ports(task, p); 291 292 continue; 293 } 294 295 nxt_port_mmaps_destroy(&p->incoming, 0); 296 297 } nxt_runtime_process_loop; 298 299 if (init->siblings != NULL) { 300 nxt_queue_each(p, init->siblings, nxt_process_t, link) { 301 302 nxt_debug(task, "remove sibling process %PI", p->pid); 303 304 nxt_process_close_ports(task, p); 305 306 } nxt_queue_loop; 307 } 308 309 return NXT_OK; 310 } 311 312 313 static nxt_pid_t 314 nxt_process_create(nxt_task_t *task, nxt_process_t *process) 315 { 316 nxt_int_t ret; 317 nxt_pid_t pid; 318 nxt_runtime_t *rt; 319 320 #if (NXT_HAVE_CLONE) 321 pid = nxt_clone(SIGCHLD | process->isolation.clone.flags); 322 if (nxt_slow_path(pid < 0)) { 323 nxt_alert(task, "clone() failed for %s %E", process->name, nxt_errno); 324 return pid; 325 } 326 #else 327 pid = fork(); 328 if (nxt_slow_path(pid < 0)) { 329 nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno); 330 return pid; 331 } 332 #endif 333 334 if (pid == 0) { 335 /* Child. */ 336 337 ret = nxt_process_child_fixup(task, process); 338 if (nxt_slow_path(ret != NXT_OK)) { 339 nxt_process_quit(task, 1); 340 return -1; 341 } 342 343 ret = nxt_process_setup(task, process); 344 if (nxt_slow_path(ret != NXT_OK)) { 345 nxt_process_quit(task, 1); 346 } 347 348 /* 349 * Explicitly return 0 to notice the caller function this is the child. 350 * The caller must return to the event engine work queue loop. 351 */ 352 return 0; 353 } 354 355 /* Parent. */ 356 357 #if (NXT_HAVE_CLONE) 358 nxt_debug(task, "clone(%s): %PI", process->name, pid); 359 #else 360 nxt_debug(task, "fork(%s): %PI", process->name, pid); 361 #endif 362 363 process->pid = pid; 364 process->isolated_pid = pid; 365 366 rt = task->thread->runtime; 367 368 if (rt->is_pid_isolated) { 369 /* 370 * Do not register process in runtime with isolated pid. 371 * Only global pid can be the key to avoid clash. 372 */ 373 nxt_assert(!nxt_queue_is_empty(&process->ports)); 374 375 nxt_port_use(task, nxt_process_port_first(process), 1); 376 377 } else { 378 nxt_runtime_process_add(task, process); 379 } 380 381 return pid; 382 } 383 384 385 static nxt_int_t 386 nxt_process_setup(nxt_task_t *task, nxt_process_t *process) 387 { 388 nxt_int_t ret; 389 nxt_thread_t *thread; 390 nxt_runtime_t *rt; 391 nxt_process_init_t *init; 392 nxt_event_engine_t *engine; 393 const nxt_event_interface_t *interface; 394 395 init = nxt_process_init(process); 396 397 nxt_debug(task, "%s setup", process->name); 398 399 nxt_process_title(task, "unit: %s", process->name); 400 401 thread = task->thread; 402 rt = thread->runtime; 403 404 nxt_random_init(&thread->random); 405 406 rt->type = init->type; 407 408 engine = thread->engine; 409 410 /* Update inherited main process event engine and signals processing. */ 411 engine->signals->sigev = init->signals; 412 413 interface = nxt_service_get(rt->services, "engine", rt->engine); 414 if (nxt_slow_path(interface == NULL)) { 415 return NXT_ERROR; 416 } 417 418 if (nxt_event_engine_change(engine, interface, rt->batch) != NXT_OK) { 419 return NXT_ERROR; 420 } 421 422 ret = nxt_runtime_thread_pool_create(thread, rt, rt->auxiliary_threads, 423 60000 * 1000000LL); 424 if (nxt_slow_path(ret != NXT_OK)) { 425 return NXT_ERROR; 426 } 427 428 nxt_port_read_close(process->parent_port); 429 nxt_port_write_enable(task, process->parent_port); 430 431 /* 432 * If the parent process is already isolated, rt->pid_isolation is already 433 * set to 1 at this point. 434 */ 435 if (nxt_is_pid_isolated(process)) { 436 rt->is_pid_isolated = 1; 437 } 438 439 if (rt->is_pid_isolated 440 || process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) 441 { 442 ret = nxt_process_whoami(task, process); 443 444 } else { 445 ret = nxt_process_do_start(task, process); 446 } 447 448 return ret; 449 } 450 451 452 static nxt_int_t 453 nxt_process_do_start(nxt_task_t *task, nxt_process_t *process) 454 { 455 nxt_int_t ret; 456 nxt_port_t *port; 457 nxt_process_init_t *init; 458 459 nxt_runtime_process_add(task, process); 460 461 init = nxt_process_init(process); 462 port = nxt_process_port_first(process); 463 464 nxt_port_enable(task, port, init->port_handlers); 465 466 ret = init->setup(task, process); 467 if (nxt_slow_path(ret != NXT_OK)) { 468 return NXT_ERROR; 469 } 470 471 switch (process->state) { 472 473 case NXT_PROCESS_STATE_CREATED: 474 ret = nxt_process_send_created(task, process); 475 break; 476 477 case NXT_PROCESS_STATE_READY: 478 ret = nxt_process_send_ready(task, process); 479 480 if (nxt_slow_path(ret != NXT_OK)) { 481 break; 482 } 483 484 ret = init->start(task, &process->data); 485 486 nxt_port_write_close(port); 487 488 break; 489 490 default: 491 nxt_assert(0); 492 } 493 494 if (nxt_slow_path(ret != NXT_OK)) { 495 nxt_alert(task, "%s failed to start", process->name); 496 } 497 498 return ret; 499 } 500 501 502 static nxt_int_t 503 nxt_process_whoami(nxt_task_t *task, nxt_process_t *process) 504 { 505 uint32_t stream; 506 nxt_fd_t fd; 507 nxt_buf_t *buf; 508 nxt_int_t ret; 509 nxt_port_t *my_port, *main_port; 510 nxt_runtime_t *rt; 511 512 rt = task->thread->runtime; 513 514 my_port = nxt_process_port_first(process); 515 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 516 517 nxt_assert(my_port != NULL && main_port != NULL); 518 519 nxt_port_enable(task, my_port, &nxt_process_whoami_port_handlers); 520 521 buf = nxt_buf_mem_alloc(main_port->mem_pool, sizeof(nxt_pid_t), 0); 522 if (nxt_slow_path(buf == NULL)) { 523 return NXT_ERROR; 524 } 525 526 buf->mem.free = nxt_cpymem(buf->mem.free, &nxt_ppid, sizeof(nxt_pid_t)); 527 528 stream = nxt_port_rpc_register_handler(task, my_port, 529 nxt_process_whoami_ok, 530 nxt_process_whoami_error, 531 main_port->pid, process); 532 if (nxt_slow_path(stream == 0)) { 533 nxt_mp_free(main_port->mem_pool, buf); 534 535 return NXT_ERROR; 536 } 537 538 fd = (process->parent_port != main_port) ? my_port->pair[1] : -1; 539 540 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_WHOAMI, 541 fd, stream, my_port->id, buf); 542 543 if (nxt_slow_path(ret != NXT_OK)) { 544 nxt_alert(task, "%s failed to send WHOAMI message", process->name); 545 nxt_port_rpc_cancel(task, my_port, stream); 546 nxt_mp_free(main_port->mem_pool, buf); 547 548 return NXT_ERROR; 549 } 550 551 return NXT_OK; 552 } 553 554 555 static void 556 nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 557 { 558 nxt_pid_t pid, isolated_pid; 559 nxt_buf_t *buf; 560 nxt_port_t *port; 561 nxt_process_t *process; 562 nxt_runtime_t *rt; 563 564 process = data; 565 566 buf = msg->buf; 567 568 nxt_assert(nxt_buf_used_size(buf) == sizeof(nxt_pid_t)); 569 570 nxt_memcpy(&pid, buf->mem.pos, sizeof(nxt_pid_t)); 571 572 isolated_pid = nxt_pid; 573 574 if (isolated_pid != pid) { 575 nxt_pid = pid; 576 process->pid = pid; 577 578 nxt_process_port_each(process, port) { 579 port->pid = pid; 580 } nxt_process_port_loop; 581 } 582 583 rt = task->thread->runtime; 584 585 if (process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) { 586 port = process->parent_port; 587 588 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_PROCESS_CREATED, 589 -1, 0, 0, NULL); 590 591 nxt_log(task, NXT_LOG_INFO, "%s started", process->name); 592 } 593 594 if (nxt_slow_path(nxt_process_do_start(task, process) != NXT_OK)) { 595 nxt_process_quit(task, 1); 596 } 597 } 598 599 600 static void 601 nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 602 { 603 nxt_alert(task, "WHOAMI error"); 604 605 nxt_process_quit(task, 1); 606 } 607 608 609 static nxt_int_t 610 nxt_process_send_created(nxt_task_t *task, nxt_process_t *process) 611 { 612 uint32_t stream; 613 nxt_int_t ret; 614 nxt_port_t *my_port, *main_port; 615 nxt_runtime_t *rt; 616 617 nxt_assert(process->state == NXT_PROCESS_STATE_CREATED); 618 619 rt = task->thread->runtime; 620 621 my_port = nxt_process_port_first(process); 622 main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 623 624 nxt_assert(my_port != NULL && main_port != NULL); 625 626 stream = nxt_port_rpc_register_handler(task, my_port, 627 nxt_process_created_ok, 628 nxt_process_created_error, 629 main_port->pid, process); 630 631 if (nxt_slow_path(stream == 0)) { 632 return NXT_ERROR; 633 } 634 635 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_CREATED, 636 -1, stream, my_port->id, NULL); 637 638 if (nxt_slow_path(ret != NXT_OK)) { 639 nxt_alert(task, "%s failed to send CREATED message", process->name); 640 nxt_port_rpc_cancel(task, my_port, stream); 641 return NXT_ERROR; 642 } 643 644 nxt_debug(task, "%s created", process->name); 645 646 return NXT_OK; 647 } 648 649 650 static void 651 nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 652 { 653 nxt_int_t ret; 654 nxt_process_t *process; 655 nxt_process_init_t *init; 656 657 process = data; 658 659 process->state = NXT_PROCESS_STATE_READY; 660 661 init = nxt_process_init(process); 662 663 ret = nxt_process_apply_creds(task, process); 664 if (nxt_slow_path(ret != NXT_OK)) { 665 goto fail; 666 } 667 668 nxt_log(task, NXT_LOG_INFO, "%s started", process->name); 669 670 ret = nxt_process_send_ready(task, process); 671 if (nxt_slow_path(ret != NXT_OK)) { 672 goto fail; 673 } 674 675 ret = init->start(task, &process->data); 676 677 if (nxt_process_type(process) != NXT_PROCESS_PROTOTYPE) { 678 nxt_port_write_close(nxt_process_port_first(process)); 679 } 680 681 if (nxt_fast_path(ret == NXT_OK)) { 682 return; 683 } 684 685 fail: 686 nxt_process_quit(task, 1); 687 } 688 689 690 static void 691 nxt_process_created_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, 692 void *data) 693 { 694 nxt_process_t *process; 695 nxt_process_init_t *init; 696 697 process = data; 698 init = nxt_process_init(process); 699 700 nxt_alert(task, "%s failed to start", init->name); 701 702 nxt_process_quit(task, 1); 703 } 704 705 706 nxt_int_t 707 nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process) 708 { 709 nxt_int_t ret; 710 711 ret = nxt_process_apply_creds(task, process); 712 if (nxt_slow_path(ret != NXT_OK)) { 713 return NXT_ERROR; 714 } 715 716 process->state = NXT_PROCESS_STATE_READY; 717 718 return NXT_OK; 719 } 720 721 722 nxt_int_t 723 nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, nxt_str_t *user, 724 nxt_str_t *group) 725 { 726 char *str; 727 728 process->user_cred = nxt_mp_zalloc(process->mem_pool, 729 sizeof(nxt_credential_t)); 730 731 if (nxt_slow_path(process->user_cred == NULL)) { 732 return NXT_ERROR; 733 } 734 735 str = nxt_mp_zalloc(process->mem_pool, user->length + 1); 736 if (nxt_slow_path(str == NULL)) { 737 return NXT_ERROR; 738 } 739 740 nxt_memcpy(str, user->start, user->length); 741 str[user->length] = '\0'; 742 743 process->user_cred->user = str; 744 745 if (group->start != NULL) { 746 str = nxt_mp_zalloc(process->mem_pool, group->length + 1); 747 if (nxt_slow_path(str == NULL)) { 748 return NXT_ERROR; 749 } 750 751 nxt_memcpy(str, group->start, group->length); 752 str[group->length] = '\0'; 753 754 } else { 755 str = NULL; 756 } 757 758 return nxt_credential_get(task, process->mem_pool, process->user_cred, str); 759 } 760 761 762 nxt_int_t 763 nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process) 764 { 765 nxt_int_t ret, cap_setid; 766 nxt_runtime_t *rt; 767 768 rt = task->thread->runtime; 769 770 cap_setid = rt->capabilities.setid; 771 772 #if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER) 773 if (!cap_setid 774 && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) 775 { 776 cap_setid = 1; 777 } 778 #endif 779 780 if (cap_setid) { 781 ret = nxt_credential_setgids(task, process->user_cred); 782 if (nxt_slow_path(ret != NXT_OK)) { 783 return NXT_ERROR; 784 } 785 786 ret = nxt_credential_setuid(task, process->user_cred); 787 if (nxt_slow_path(ret != NXT_OK)) { 788 return NXT_ERROR; 789 } 790 } 791 792 #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 793 if (nxt_slow_path(process->isolation.new_privs == 0 794 && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)) 795 { 796 nxt_alert(task, "failed to set no_new_privs %E", nxt_errno); 797 return NXT_ERROR; 798 } 799 #endif 800 801 return NXT_OK; 802 } 803 804 805 static nxt_int_t 806 nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process) 807 { 808 nxt_int_t ret; 809 810 ret = nxt_port_socket_write(task, process->parent_port, 811 NXT_PORT_MSG_PROCESS_READY, 812 -1, process->stream, 0, NULL); 813 814 if (nxt_slow_path(ret != NXT_OK)) { 815 nxt_alert(task, "%s failed to send READY message", process->name); 816 return NXT_ERROR; 817 } 818 819 nxt_debug(task, "%s sent ready", process->name); 820 821 return NXT_OK; 822 } 823 824 825 /* 826 * Linux glibc 2.2 posix_spawn() is implemented via fork()/execve(). 827 * Linux glibc 2.4 posix_spawn() without file actions and spawn 828 * attributes uses vfork()/execve(). 829 * 830 * On FreeBSD 8.0 posix_spawn() is implemented via vfork()/execve(). 831 * 832 * Solaris 10: 833 * In the Solaris 10 OS, posix_spawn() is currently implemented using 834 * private-to-libc vfork(), execve(), and exit() functions. They are 835 * identical to regular vfork(), execve(), and exit() in functionality, 836 * but they are not exported from libc and therefore don't cause the 837 * deadlock-in-the-dynamic-linker problem that any multithreaded code 838 * outside of libc that calls vfork() can cause. 839 * 840 * On MacOSX 10.5 (Leoprad) and NetBSD 6.0 posix_spawn() is implemented 841 * as syscall. 842 */ 843 844 nxt_pid_t 845 nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp) 846 { 847 nxt_pid_t pid; 848 849 nxt_debug(task, "posix_spawn(\"%s\")", name); 850 851 if (posix_spawn(&pid, name, NULL, NULL, argv, envp) != 0) { 852 nxt_alert(task, "posix_spawn(\"%s\") failed %E", name, nxt_errno); 853 return -1; 854 } 855 856 return pid; 857 } 858 859 860 nxt_int_t 861 nxt_process_daemon(nxt_task_t *task) 862 { 863 nxt_fd_t fd; 864 nxt_pid_t pid; 865 const char *msg; 866 867 fd = -1; 868 869 /* 870 * fork() followed by a parent process's exit() detaches a child process 871 * from an init script or terminal shell process which has started the 872 * parent process and allows the child process to run in background. 873 */ 874 875 pid = fork(); 876 877 switch (pid) { 878 879 case -1: 880 msg = "fork() failed %E"; 881 goto fail; 882 883 case 0: 884 /* A child. */ 885 break; 886 887 default: 888 /* A parent. */ 889 nxt_debug(task, "fork(): %PI", pid); 890 exit(0); 891 nxt_unreachable(); 892 } 893 894 nxt_pid = getpid(); 895 896 /* Clean inherited cached thread tid. */ 897 task->thread->tid = 0; 898 899 nxt_debug(task, "daemon"); 900 901 /* Detach from controlling terminal. */ 902 903 if (setsid() == -1) { 904 nxt_alert(task, "setsid() failed %E", nxt_errno); 905 return NXT_ERROR; 906 } 907 908 /* 909 * Reset file mode creation mask: any access 910 * rights can be set on file creation. 911 */ 912 umask(0); 913 914 /* Redirect STDIN and STDOUT to the "/dev/null". */ 915 916 fd = open("/dev/null", O_RDWR); 917 if (fd == -1) { 918 msg = "open(\"/dev/null\") failed %E"; 919 goto fail; 920 } 921 922 if (dup2(fd, STDIN_FILENO) == -1) { 923 msg = "dup2(\"/dev/null\", STDIN) failed %E"; 924 goto fail; 925 } 926 927 if (dup2(fd, STDOUT_FILENO) == -1) { 928 msg = "dup2(\"/dev/null\", STDOUT) failed %E"; 929 goto fail; 930 } 931 932 if (fd > STDERR_FILENO) { 933 nxt_fd_close(fd); 934 } 935 936 return NXT_OK; 937 938 fail: 939 940 nxt_alert(task, msg, nxt_errno); 941 942 if (fd != -1) { 943 nxt_fd_close(fd); 944 } 945 946 return NXT_ERROR; 947 } 948 949 950 void 951 nxt_nanosleep(nxt_nsec_t ns) 952 { 953 struct timespec ts; 954 955 ts.tv_sec = ns / 1000000000; 956 ts.tv_nsec = ns % 1000000000; 957 958 (void) nanosleep(&ts, NULL); 959 } 960 961 962 void 963 nxt_process_port_add(nxt_task_t *task, nxt_process_t *process, nxt_port_t *port) 964 { 965 nxt_assert(port->process == NULL); 966 967 port->process = process; 968 nxt_queue_insert_tail(&process->ports, &port->link); 969 970 nxt_process_use(task, process, 1); 971 } 972 973 974 nxt_process_type_t 975 nxt_process_type(nxt_process_t *process) 976 { 977 return nxt_queue_is_empty(&process->ports) ? 0 : 978 (nxt_process_port_first(process))->type; 979 } 980 981 982 void 983 nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process) 984 { 985 nxt_port_t *port; 986 987 nxt_process_use(task, process, 1); 988 989 nxt_process_port_each(process, port) { 990 991 nxt_port_close(task, port); 992 993 nxt_runtime_port_remove(task, port); 994 995 } nxt_process_port_loop; 996 997 nxt_process_use(task, process, -1); 998 } 999 1000 1001 void 1002 nxt_process_quit(nxt_task_t *task, nxt_uint_t exit_status) 1003 { 1004 nxt_uint_t n; 1005 nxt_queue_t *listen; 1006 nxt_runtime_t *rt; 1007 nxt_queue_link_t *link, *next; 1008 nxt_listen_event_t *lev; 1009 nxt_listen_socket_t *ls; 1010 1011 rt = task->thread->runtime; 1012 1013 nxt_debug(task, "close listen connections"); 1014 1015 listen = &task->thread->engine->listen_connections; 1016 1017 for (link = nxt_queue_first(listen); 1018 link != nxt_queue_tail(listen); 1019 link = next) 1020 { 1021 next = nxt_queue_next(link); 1022 lev = nxt_queue_link_data(link, nxt_listen_event_t, link); 1023 nxt_queue_remove(link); 1024 1025 nxt_fd_event_close(task->thread->engine, &lev->socket); 1026 } 1027 1028 if (rt->listen_sockets != NULL) { 1029 1030 ls = rt->listen_sockets->elts; 1031 n = rt->listen_sockets->nelts; 1032 1033 while (n != 0) { 1034 nxt_socket_close(task, ls->socket); 1035 ls->socket = -1; 1036 1037 ls++; 1038 n--; 1039 } 1040 1041 rt->listen_sockets->nelts = 0; 1042 } 1043 1044 nxt_runtime_quit(task, exit_status); 1045 } 1046