diff options
| author | jimmy <[email protected]> | 2022-02-10 16:49:38 +0300 | 
|---|---|---|
| committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:49:38 +0300 | 
| commit | 5ab412f19b9312abbfa362391df45d6603bb84c3 (patch) | |
| tree | 5d5cb817648f650d76cf1076100726fd9b8448e8 /util/system | |
| parent | affdafdb1fc09bf0bfc384355143ee6db9e90046 (diff) | |
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'util/system')
| -rw-r--r-- | util/system/shellcommand.cpp | 82 | ||||
| -rw-r--r-- | util/system/shellcommand.h | 64 | ||||
| -rw-r--r-- | util/system/shellcommand_ut.cpp | 96 | 
3 files changed, 121 insertions, 121 deletions
diff --git a/util/system/shellcommand.cpp b/util/system/shellcommand.cpp index e253cc99be5..b1989b5c8c3 100644 --- a/util/system/shellcommand.cpp +++ b/util/system/shellcommand.cpp @@ -291,8 +291,8 @@ public:          , ErrorStream(options.ErrorStream)          , WatchThread(nullptr)          , TerminateFlag(false) -        , ClearSignalMask(options.ClearSignalMask)  -        , CloseAllFdsOnExec(options.CloseAllFdsOnExec)  +        , ClearSignalMask(options.ClearSignalMask) +        , CloseAllFdsOnExec(options.CloseAllFdsOnExec)          , AsyncMode(options.AsyncMode)          , PollDelayMs(options.PollDelayMs)          , UseShell(options.UseShell) @@ -389,25 +389,25 @@ public:      // start child process      void Run(); -    inline void Terminate() {  +    inline void Terminate() {          if (!!Pid && (AtomicGet(ExecutionStatus) == SHELL_RUNNING)) {              bool ok =  #if defined(_unix_)                  kill(DetachSession ? -1 * Pid : Pid, SIGTERM) == 0; -            if (!ok && (errno == ESRCH) && DetachSession) {  -                // this could fail when called before child proc completes setsid().  -                ok = kill(Pid, SIGTERM) == 0;  +            if (!ok && (errno == ESRCH) && DetachSession) { +                // this could fail when called before child proc completes setsid(). +                ok = kill(Pid, SIGTERM) == 0;                  kill(-Pid, SIGTERM); // between a failed kill(-Pid) and a successful kill(Pid) a grandchild could have been spawned -            }  +            }  #else                  TerminateProcess(Pid, 1 /* exit code */);  #endif              if (!ok) {                  ythrow TSystemError() << "cannot terminate " << Pid;              } -        }  -    }  -  +        } +    } +      inline void Wait() {          if (WatchThread) {              WatchThread->Join(); @@ -670,24 +670,24 @@ void TShellCommand::TImpl::OnFork(TPipes& pipes, sigset_t oldmask, char* const*          if (DetachSession) {              setsid();          } -  -        // reset signal handlers from parent  -        struct sigaction sa;  -        sa.sa_handler = SIG_DFL;  -        sa.sa_flags = 0;  -        SigEmptySet(&sa.sa_mask);  -        for (int i = 0; i < NSIG; ++i) {  -            // some signals cannot be caught, so just ignore return value  + +        // reset signal handlers from parent +        struct sigaction sa; +        sa.sa_handler = SIG_DFL; +        sa.sa_flags = 0; +        SigEmptySet(&sa.sa_mask); +        for (int i = 0; i < NSIG; ++i) { +            // some signals cannot be caught, so just ignore return value              sigaction(i, &sa, nullptr); -        }  -        if (ClearSignalMask) {  -            SigEmptySet(&oldmask);  -        }  -        // clear / restore signal mask  +        } +        if (ClearSignalMask) { +            SigEmptySet(&oldmask); +        } +        // clear / restore signal mask          if (SigProcMask(SIG_SETMASK, &oldmask, nullptr) != 0) { -            ythrow TSystemError() << "Cannot " << (ClearSignalMask ? "clear" : "restore") << " signal mask in child";  -        }  -  +            ythrow TSystemError() << "Cannot " << (ClearSignalMask ? "clear" : "restore") << " signal mask in child"; +        } +          TFileHandle sIn(0);          TFileHandle sOut(1);          TFileHandle sErr(2); @@ -775,13 +775,13 @@ void TShellCommand::TImpl::Run() {      AtomicSet(ExecutionStatus, SHELL_RUNNING);  #if defined(_unix_) -    // block all signals to avoid signal handler race after fork()  -    sigset_t oldmask, newmask;  -    SigFillSet(&newmask);  -    if (SigProcMask(SIG_SETMASK, &newmask, &oldmask) != 0) {  -        ythrow TSystemError() << "Cannot block all signals in parent";  -    }  -  +    // block all signals to avoid signal handler race after fork() +    sigset_t oldmask, newmask; +    SigFillSet(&newmask); +    if (SigProcMask(SIG_SETMASK, &newmask, &oldmask) != 0) { +        ythrow TSystemError() << "Cannot block all signals in parent"; +    } +      /* arguments holders */      TString shellArg;      TVector<char*> qargv; @@ -828,11 +828,11 @@ void TShellCommand::TImpl::Run() {          } else {              OnFork(pipes, oldmask, qargv.data(), nullptr, FuncAfterFork);          } -    } else { // parent  -        // restore signal mask  +    } else { // parent +        // restore signal mask          if (SigProcMask(SIG_SETMASK, &oldmask, nullptr) != 0) { -            ythrow TSystemError() << "Cannot restore signal mask in parent";  -        }  +            ythrow TSystemError() << "Cannot restore signal mask in parent"; +        }      }      Pid = pid;  #else @@ -1181,10 +1181,10 @@ TShellCommand& TShellCommand::Run() {  }  TShellCommand& TShellCommand::Terminate() { -    Impl->Terminate();  -    return *this;  -}  -  +    Impl->Terminate(); +    return *this; +} +  TShellCommand& TShellCommand::Wait() {      Impl->Wait();      return *this; diff --git a/util/system/shellcommand.h b/util/system/shellcommand.h index 8498953ff62..8730627fe5b 100644 --- a/util/system/shellcommand.h +++ b/util/system/shellcommand.h @@ -67,33 +67,33 @@ public:      /**       * @brief clear signal mask from parent process. If true, child process -     * clears the signal mask inherited from the parent process; otherwise  -     * child process retains the signal mask of the parent process.  -     *  -     * @param clearSignalMask true if child process should clear signal mask  -     * @note in default child process inherits signal mask.  -     * @return self  -     */  -    inline TShellCommandOptions& SetClearSignalMask(bool clearSignalMask) {  -        ClearSignalMask = clearSignalMask;  -        return *this;  -    }  -  -    /**  +     * clears the signal mask inherited from the parent process; otherwise +     * child process retains the signal mask of the parent process. +     * +     * @param clearSignalMask true if child process should clear signal mask +     * @note in default child process inherits signal mask. +     * @return self +     */ +    inline TShellCommandOptions& SetClearSignalMask(bool clearSignalMask) { +        ClearSignalMask = clearSignalMask; +        return *this; +    } + +    /**       * @brief set close-on-exec mode. If true, all file descriptors -     * from the parent process, except stdin, stdout, stderr, will be closed  -     * in the child process upon exec().  -     *  -     * @param closeAllFdsOnExec true if close-on-exec mode is needed  -     * @note in default close-on-exec mode is off.  -     * @return self  -     */  +     * from the parent process, except stdin, stdout, stderr, will be closed +     * in the child process upon exec(). +     * +     * @param closeAllFdsOnExec true if close-on-exec mode is needed +     * @note in default close-on-exec mode is off. +     * @return self +     */      inline TShellCommandOptions& SetCloseAllFdsOnExec(bool closeAllFdsOnExec) { -        CloseAllFdsOnExec = closeAllFdsOnExec;  -        return *this;  -    }  -  -    /**  +        CloseAllFdsOnExec = closeAllFdsOnExec; +        return *this; +    } + +    /**       * @brief set asynchronous mode. If true, task will be run       * in separate thread, and control will be returned immediately       * @@ -443,14 +443,14 @@ public:      TShellCommand& Run();      /** -     * @brief terminate the execution  -     * @note if DetachSession is set, it terminates all procs in command's new process group  -     *  -     * @return self  -     */  +     * @brief terminate the execution +     * @note if DetachSession is set, it terminates all procs in command's new process group +     * +     * @return self +     */      TShellCommand& Terminate(); -  -    /**  + +    /**       * @brief wait until the execution is finished       *       * @return self diff --git a/util/system/shellcommand_ut.cpp b/util/system/shellcommand_ut.cpp index 5df3277fae3..9d849279d23 100644 --- a/util/system/shellcommand_ut.cpp +++ b/util/system/shellcommand_ut.cpp @@ -229,7 +229,7 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {          options.SetAsync(true);          options.SetQuoteArguments(false);          options.SetLatency(10); -        options.SetClearSignalMask(true);  +        options.SetClearSignalMask(true);          options.SetCloseAllFdsOnExec(true);          options.SetCloseInput(false);          TGuardedStringStream write; @@ -308,66 +308,66 @@ Y_UNIT_TEST_SUITE(TShellCommandTest) {              cmd.Run();              sleep(1);              UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus()); -            // Async mode requires Terminate() + Wait() to send kill to child proc!  -            cmd.Terminate();  -            cmd.Wait();  -            UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus());  +            // Async mode requires Terminate() + Wait() to send kill to child proc! +            cmd.Terminate(); +            cmd.Wait(); +            UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus());              UNIT_ASSERT(cmd.GetExitCode().Defined() && -15 == cmd.GetExitCode());          }          sleep(1);          UNIT_ASSERT(!NFs::Exists(tmpfile));      } -    // this ut is unix-only (win has no signal mask)  +    // this ut is unix-only (win has no signal mask)      Y_UNIT_TEST(TestSignalMask) { -        // block SIGTERM  -        int rc;  -        sigset_t newmask, oldmask;  -        SigEmptySet(&newmask);  -        SigAddSet(&newmask, SIGTERM);  -        rc = SigProcMask(SIG_SETMASK, &newmask, &oldmask);  -        UNIT_ASSERT(rc == 0);  -  +        // block SIGTERM +        int rc; +        sigset_t newmask, oldmask; +        SigEmptySet(&newmask); +        SigAddSet(&newmask, SIGTERM); +        rc = SigProcMask(SIG_SETMASK, &newmask, &oldmask); +        UNIT_ASSERT(rc == 0); +          TString tmpfile = TString("shellcommand_ut.interrupt.") + ToString(RandomNumber<ui32>()); -  -        TShellCommandOptions options;  -        options.SetAsync(true);  -        options.SetQuoteArguments(false);  -  -        // child proc should not receive SIGTERM anymore  -        {  -            TShellCommand cmd("/bin/sleep", options);  -            // touch file only if sleep not interrupted by SIGTERM  + +        TShellCommandOptions options; +        options.SetAsync(true); +        options.SetQuoteArguments(false); + +        // child proc should not receive SIGTERM anymore +        { +            TShellCommand cmd("/bin/sleep", options); +            // touch file only if sleep not interrupted by SIGTERM              cmd << " 10 & wait; [ $? == 0 ] || /usr/bin/touch " << tmpfile; -            cmd.Run();  -            sleep(1);  -            UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus());  -            cmd.Terminate();  -            cmd.Wait();  +            cmd.Run(); +            sleep(1); +            UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus()); +            cmd.Terminate(); +            cmd.Wait();              UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus() || TShellCommand::SHELL_FINISHED == cmd.GetStatus()); -        }  -        sleep(1);  +        } +        sleep(1);          UNIT_ASSERT(!NFs::Exists(tmpfile)); -  -        // child proc should receive SIGTERM  -        options.SetClearSignalMask(true);  -        {  -            TShellCommand cmd("/bin/sleep", options);  -            // touch file regardless -- it will be interrupted  + +        // child proc should receive SIGTERM +        options.SetClearSignalMask(true); +        { +            TShellCommand cmd("/bin/sleep", options); +            // touch file regardless -- it will be interrupted              cmd << " 10 & wait; /usr/bin/touch " << tmpfile; -            cmd.Run();  -            sleep(1);  -            UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus());  -            cmd.Terminate();  -            cmd.Wait();  -            UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus());  -        }  -        sleep(1);  +            cmd.Run(); +            sleep(1); +            UNIT_ASSERT(TShellCommand::SHELL_RUNNING == cmd.GetStatus()); +            cmd.Terminate(); +            cmd.Wait(); +            UNIT_ASSERT(TShellCommand::SHELL_ERROR == cmd.GetStatus()); +        } +        sleep(1);          UNIT_ASSERT(!NFs::Exists(tmpfile)); -  -        // restore signal mask  + +        // restore signal mask          rc = SigProcMask(SIG_SETMASK, &oldmask, nullptr); -        UNIT_ASSERT(rc == 0);  -    }  +        UNIT_ASSERT(rc == 0); +    }  #else      // This ut is windows-only      Y_UNIT_TEST(TestStdinProperlyConstructed) {  | 
