improve crash diagnosis/detection when a test segfaults
parent
9defbf989d
commit
60d4f47f7a
|
@ -542,9 +542,8 @@ fn (v V) run_compiled_executable_and_exit() {
|
||||||
ret := os.system(cmd)
|
ret := os.system(cmd)
|
||||||
// TODO: make the runner wrapping as transparent as possible
|
// TODO: make the runner wrapping as transparent as possible
|
||||||
// (i.e. use execve when implemented). For now though, the runner
|
// (i.e. use execve when implemented). For now though, the runner
|
||||||
// just returns the same exit code as the child process
|
// just returns the same exit code as the child process.
|
||||||
// (see man system, man 2 waitpid: C macro WEXITSTATUS section)
|
exit( ret )
|
||||||
exit( ret >> 8 )
|
|
||||||
}
|
}
|
||||||
exit(0)
|
exit(0)
|
||||||
}
|
}
|
||||||
|
|
73
vlib/os/os.v
73
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 {
|
$if windows {
|
||||||
return C._pclose(f)
|
return waitret, false
|
||||||
}
|
}
|
||||||
$else {
|
$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)
|
ret = C.system(cmd.str)
|
||||||
}
|
}
|
||||||
if ret == -1 {
|
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
|
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.
|
// `getenv` returns the value of the environment variable named by the key.
|
||||||
pub fn getenv(key string) string {
|
pub fn getenv(key string) string {
|
||||||
$if windows {
|
$if windows {
|
||||||
|
@ -408,7 +471,7 @@ pub fn rmdir(path string) {
|
||||||
|
|
||||||
|
|
||||||
fn print_c_errno() {
|
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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue