/* 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 #include #ifndef WCOREDUMP #define WCOREDUMP(status) (0) #endif 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; if ((pid = fork()) < 0) throw std::runtime_error("fork error"); else if (pid == 0) /* child */ { f(); exit(0); } else/*parent*/ 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() { 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) ); // // Raise SIGFPE. // pid = fork_lambda([](){ volatile 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 ) {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; }}