From 1c568045e853765174c744023a72afaecf8293eb Mon Sep 17 00:00:00 2001 From: Vahagn Khachatryan Date: Tue, 3 Mar 2015 11:33:36 +0400 Subject: [PATCH] Also stop/continue SIGTERM/SIGKILL are tested. --- linux/fork_wait_exit_status.cpp | 113 +++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 32 deletions(-) diff --git a/linux/fork_wait_exit_status.cpp b/linux/fork_wait_exit_status.cpp index f1c332b..821ca63 100644 --- a/linux/fork_wait_exit_status.cpp +++ b/linux/fork_wait_exit_status.cpp @@ -7,6 +7,7 @@ VIM-: let g:ldlibpath=g:Bboost.g:Btbb VIM: let g:argv="" */ #include +#include #include #include @@ -16,29 +17,31 @@ VIM: let g:argv="" #define WCOREDUMP(status) (0) #endif -void pr_exit(int status) -{ - if (WIFEXITED(status)) - std::cout << "normal termination, exit status =" - << WEXITSTATUS(status) << std::endl; - else if (WIFSIGNALED(status)) - std::cout << "abnormal termination, signal number = " - << WTERMSIG(status) - << (WCOREDUMP(status) ? " (core file generated)" : "") - << std::endl; - else if (WIFSTOPPED(status)) - std::cout << "child stopped, signal number = " - << WSTOPSIG(status) << std::endl; -} - -template< class F> -void fork_and_wait( const char * caption, F&& f ) +void print_status(const char * caption, int status) { std::cout << caption << ": "; std::cout.flush(); + if (WIFEXITED(status)) + std::cout << "normal termination, exit status = " << WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + std::cout << "abnormal termination, signal number = " + << WTERMSIG(status) + << (WCOREDUMP(status) ? " (core file generated)" : ""); + else if (WIFSTOPPED(status)) + std::cout << "child stopped, signal number = " << WSTOPSIG(status); + else if (WIFCONTINUED(status)) + std::cout << "child continued"; + else + std::cout << "couldn't figure our exit reason. status = " << status; + std::cout << std::endl; + std::cout.flush(); +} + +template< class F> +pid_t fork_lambda( F&& f ) +{ pid_t pid; - int status; if ((pid = fork()) < 0) throw std::runtime_error("fork error"); else if (pid == 0) /* child */ @@ -47,28 +50,74 @@ void fork_and_wait( const char * caption, F&& f ) exit(0); } else/*parent*/ - { - if (wait(&status) != pid) /* wait for child */ - throw std::runtime_error("wait error"); - pr_exit(status); /* and print its status */ - } + return pid; +} + +int wait_for_status( pid_t pid ) +{ + int status; + if (waitpid(pid,&status,WUNTRACED|WCONTINUED) != pid) + throw std::runtime_error("wait error"); + return status; } void test() { - fork_and_wait("exit(7)", [](){ - exit(7); + pid_t pid; + // + // Normal exit. + // + pid = fork_lambda([](){ + exit(7); }); + print_status( "exit(7)", wait_for_status(pid) ); + // + // Self aborting process. + // + pid = fork_lambda([](){ + abort(); + }); + print_status( "SIGABORT through abort()", wait_for_status(pid) ); - fork_and_wait("SIGABORT through abort()", [](){ - abort(); + // + // Raise SIGFPE. + // + pid = fork_lambda([](){ + volatile int a = rand(); + int b = 0; + a /= b; }); - - fork_and_wait("SIGFPE through divison by zero", [](){ - int a = rand(); - int b = 0; - a /= b; + print_status( "SIGFPE through division by zero", wait_for_status(pid) ); + // + // Kill process. + // + pid = fork_lambda([](){ + while ( true ); }); + if (kill( pid, SIGKILL )) + throw std::runtime_error("failed to send kill signal"); + print_status( "SIGKILL is sent", wait_for_status(pid) ); + // + // Stop process. + // + pid = fork_lambda([](){ + while ( true ); + }); + if (kill( pid, SIGSTOP )) + throw std::runtime_error("failed to send stop signal"); + print_status( "SIGSTOP is sent", wait_for_status(pid) ); + // + // Resume process. + // + if (kill( pid, SIGCONT )) + throw std::runtime_error("failed to send continue signal"); + print_status( "SIGCONT is sent", wait_for_status(pid) ); + // + // Terminate process. + // + if (kill( pid, SIGTERM )) + throw std::runtime_error("failed to send termination signal"); + print_status( "SIGTERM is sent", wait_for_status(pid) ); } int main ( void )