mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
76 lines
1.5 KiB
V
76 lines
1.5 KiB
V
import os
|
|
import time
|
|
import flag
|
|
import strconv
|
|
|
|
struct Context {
|
|
mut:
|
|
timeout f64
|
|
cmd_args []string
|
|
}
|
|
|
|
fn main() {
|
|
mut fp := flag.new_flag_parser(os.args[1..])
|
|
fp.application('v timeout')
|
|
fp.version('0.0.2')
|
|
fp.description('Run a command with a time limit. Example: `v timeout 0.3 v run examples/hello_world.v`')
|
|
fp.arguments_description('timeout_in_seconds CMD [ARGS]')
|
|
fp.skip_executable()
|
|
fp.limit_free_args_to_at_least(2)!
|
|
|
|
if fp.bool('help', `h`, false, 'Show this help screen.') {
|
|
println(fp.usage())
|
|
exit(0)
|
|
}
|
|
|
|
args := fp.finalize() or {
|
|
eprintln('Argument error: ${err}')
|
|
exit(125) // mimic the exit codes of `timeout` in coreutils
|
|
}
|
|
|
|
ctx := Context{
|
|
timeout: strconv.atof64(args[0]) or {
|
|
eprintln('Invalid timeout: ${args[0]}')
|
|
exit(125)
|
|
}
|
|
cmd_args: args[1..].clone()
|
|
}
|
|
|
|
mut cmd := ctx.cmd_args[0]
|
|
if !os.exists(cmd) {
|
|
cmd = os.find_abs_path_of_executable(cmd) or { cmd }
|
|
}
|
|
|
|
mut p := os.new_process(cmd)
|
|
p.set_args(ctx.cmd_args[1..])
|
|
p.run()
|
|
if p.err != '' {
|
|
eprintln('Cannot execute: ${ctx.cmd_args.join(' ')}')
|
|
exit(if os.exists(ctx.cmd_args[0]) { 126 } else { 127 })
|
|
}
|
|
|
|
child_exit := chan int{}
|
|
|
|
spawn fn (mut p os.Process, ch chan int) {
|
|
p.wait()
|
|
ch <- p.code
|
|
ch.close()
|
|
}(mut p, child_exit)
|
|
|
|
mut exit_code := 0
|
|
select {
|
|
i64(ctx.timeout * time.second) {
|
|
p.signal_term()
|
|
time.sleep(2 * time.millisecond)
|
|
if p.is_alive() {
|
|
p.signal_kill()
|
|
}
|
|
p.wait()
|
|
exit_code = 124 // timeout
|
|
}
|
|
code := <-child_exit {
|
|
exit_code = code
|
|
}
|
|
}
|
|
exit(exit_code)
|
|
}
|