diff --git a/compiler/main.v b/compiler/main.v index 14b7dd3c2c..8a16e2d961 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -542,9 +542,8 @@ fn (v V) run_compiled_executable_and_exit() { ret := os.system(cmd) // TODO: make the runner wrapping as transparent as possible // (i.e. use execve when implemented). For now though, the runner - // just returns the same exit code as the child process - // (see man system, man 2 waitpid: C macro WEXITSTATUS section) - exit( ret >> 8 ) + // just returns the same exit code as the child process. + exit( ret ) } exit(0) } diff --git a/vlib/os/os.v b/vlib/os/os.v index 20c2532683..f966f2691b 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -279,12 +279,32 @@ fn popen(path string) *C.FILE { } } -fn pclose(f *C.FILE) int { +fn posix_wait4_to_exit_status(waitret int) (int,bool) { $if windows { - return C._pclose(f) + return waitret, false } $else { - return C.pclose(f) / 256 // WEXITSTATUS() + mut ret := 0 + mut is_signaled := true + // (see man system, man 2 waitpid: C macro WEXITSTATUS section) + if C.WIFEXITED( waitret ) { + ret = C.WEXITSTATUS( waitret ) + is_signaled = false + } else if C.WIFSIGNALED( waitret ){ + ret = C.WTERMSIG( waitret ) + is_signaled = true + } + return ret , is_signaled + } +} + +fn pclose(f *C.FILE) int { + $if windows { + return int( C._pclose(f) ) + } + $else { + ret , _ := posix_wait4_to_exit_status( int( C.pclose(f) ) ) + return ret } } @@ -326,11 +346,54 @@ pub fn system(cmd string) int { ret = C.system(cmd.str) } if ret == -1 { - os.print_c_errno() + print_c_errno() + } + + $if !windows { + pret , is_signaled := posix_wait4_to_exit_status( ret ) + if is_signaled { + println('Terminated by signal ${ret:2d} (' + sigint_to_signal_name(pret) + ')' ) + } + ret = pret } return ret } +pub fn sigint_to_signal_name(si int) string { + // POSIX signals: + switch si { + case 1: return 'SIGHUP' + case 2: return 'SIGINT' + case 3: return 'SIGQUIT' + case 4: return 'SIGILL' + case 6: return 'SIGABRT' + case 8: return 'SIGFPE' + case 9: return 'SIGKILL' + case 11: return 'SIGSEGV' + case 13: return 'SIGPIPE' + case 14: return 'SIGALRM' + case 15: return 'SIGTERM' + } + /////////////////////////////////// + $if linux { + // From `man 7 signal` on linux: + switch si { + case 30,10,16: return 'SIGUSR1' + case 31,12,17: return 'SIGUSR2' + case 20,17,18: return 'SIGCHLD' + case 19,18,25: return 'SIGCONT' + case 17,19,23: return 'SIGSTOP' + case 18,20,24: return 'SIGTSTP' + case 21,21,26: return 'SIGTTIN' + case 22,22,27: return 'SIGTTOU' + /////////////////////////////// + case 5: return 'SIGTRAP' + case 7: return 'SIGBUS' + } + } + return 'unknown' +} + // `getenv` returns the value of the environment variable named by the key. pub fn getenv(key string) string { $if windows { @@ -408,7 +471,7 @@ pub fn rmdir(path string) { fn print_c_errno() { - //C.printf('errno=%d err="%s"\n', errno, C.strerror(errno)) + //C.printf('errno=%d err="%s"\n', C.errno, C.strerror(C.errno)) }