diff --git a/linux/fork_wait.cpp b/linux/fork_wait.cpp new file mode 100644 index 0000000..f1c332b --- /dev/null +++ b/linux/fork_wait.cpp @@ -0,0 +1,91 @@ +/* +VIM: let g:lcppflags="-std=c++11 -O2 -pthread" +VIM: let g:wcppflags="/O2 /EHsc /DWIN32" +VIM-: let g:cppflags=g:Iboost.g:Itbb +VIM-: let g:ldflags=g:Lboost.g:Ltbb.g:tbbmalloc.g:tbbmproxy +VIM-: let g:ldlibpath=g:Bboost.g:Btbb +VIM: let g:argv="" +*/ +#include +#include + +#include +#include + +#ifndef WCOREDUMP +#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 ) +{ + std::cout << caption << ": "; + std::cout.flush(); + + pid_t pid; + int status; + if ((pid = fork()) < 0) + throw std::runtime_error("fork error"); + else if (pid == 0) /* child */ + { + 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 */ + } +} + +void test() +{ + fork_and_wait("exit(7)", [](){ + exit(7); + }); + + fork_and_wait("SIGABORT through abort()", [](){ + abort(); + }); + + fork_and_wait("SIGFPE through divison by zero", [](){ + int a = rand(); + int b = 0; + a /= b; + }); +} + +int main ( void ) +{try{ + test(); + return 0; +} +catch ( const std::exception& e ) +{ + std::cerr << std::endl + << "std::exception(\"" << e.what() << "\")." << std::endl; + return 2; +} +catch ( ... ) +{ + std::cerr << std::endl + << "unknown exception." << std::endl; + return 1; +}} +