| 638 | |
| 639 | #if defined(_unix_) |
| 640 | void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const* argv, char* const* envp, const std::function<void()>& afterFork) const { |
| 641 | try { |
| 642 | if (Options_.DetachSession) { |
| 643 | setsid(); |
| 644 | } |
| 645 | |
| 646 | // reset signal handlers from parent |
| 647 | struct sigaction sa; |
| 648 | sa.sa_handler = SIG_DFL; |
| 649 | sa.sa_flags = 0; |
| 650 | SigEmptySet(&sa.sa_mask); |
| 651 | for (int i = 0; i < NSIG; ++i) { |
| 652 | // some signals cannot be caught, so just ignore return value |
| 653 | sigaction(i, &sa, nullptr); |
| 654 | } |
| 655 | if (Options_.ClearSignalMask) { |
| 656 | SigEmptySet(&oldmask); |
| 657 | } |
| 658 | // clear / restore signal mask |
| 659 | if (SigProcMask(SIG_SETMASK, &oldmask, nullptr) != 0) { |
| 660 | ythrow TSystemError() << "Cannot " << (Options_.ClearSignalMask ? "clear" : "restore") << " signal mask in child"; |
| 661 | } |
| 662 | |
| 663 | TFileHandle sIn(0); |
| 664 | TFileHandle sOut(1); |
| 665 | TFileHandle sErr(2); |
| 666 | if (InputMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 667 | pipes.InputPipeFd[1].Close(); |
| 668 | TFileHandle sInNew(pipes.InputPipeFd[0]); |
| 669 | sIn.LinkTo(sInNew); |
| 670 | sIn.Release(); |
| 671 | sInNew.Release(); |
| 672 | } else { |
| 673 | // do not close fd 0 - next open will return it and confuse all readers |
| 674 | /// @todo in case of real need - reopen /dev/null |
| 675 | } |
| 676 | if (Options_.OutputMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 677 | pipes.OutputPipeFd[0].Close(); |
| 678 | TFileHandle sOutNew(pipes.OutputPipeFd[1]); |
| 679 | sOut.LinkTo(sOutNew); |
| 680 | sOut.Release(); |
| 681 | sOutNew.Release(); |
| 682 | } |
| 683 | if (Options_.ErrorMode != TShellCommandOptions::HANDLE_INHERIT) { |
| 684 | pipes.ErrorPipeFd[0].Close(); |
| 685 | TFileHandle sErrNew(pipes.ErrorPipeFd[1]); |
| 686 | sErr.LinkTo(sErrNew); |
| 687 | sErr.Release(); |
| 688 | sErrNew.Release(); |
| 689 | } |
| 690 | |
| 691 | if (WorkDir.size()) { |
| 692 | NFs::SetCurrentWorkingDirectory(WorkDir); |
| 693 | } |
| 694 | |
| 695 | if (Options_.CloseAllFdsOnExec) { |
| 696 | for (int fd = NSystemInfo::MaxOpenFiles(); fd > STDERR_FILENO; --fd) { |
| 697 | fcntl(fd, F_SETFD, FD_CLOEXEC); |
nothing calls this directly
no test coverage detected