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