improve crash diagnosis/detection when a test segfaults

pull/2257/head
Delyan Angelov 2019-10-08 02:34:55 +03:00 committed by Alexander Medvednikov
parent 9defbf989d
commit 60d4f47f7a
2 changed files with 70 additions and 8 deletions

View File

@ -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)
} }

View File

@ -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))
} }