From 4ac751d773c9a8540e9a615cdb4e7a4e2b5da26a Mon Sep 17 00:00:00 2001 From: Enzo Date: Wed, 5 May 2021 14:39:02 +0200 Subject: [PATCH] os: add `signal_opt` and deprecate `signal` (#10005) --- vlib/builtin/cfns.c.v | 2 -- vlib/os/os_c.v | 6 ----- vlib/os/signal.c.v | 58 +++++++++++++++++++++++++++++++++++++++++ vlib/os/signal_test.v | 35 +++++++++++++++++++++++++ vlib/v/gen/c/cheaders.v | 2 -- 5 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 vlib/os/signal.c.v create mode 100644 vlib/os/signal_test.v diff --git a/vlib/builtin/cfns.c.v b/vlib/builtin/cfns.c.v index 6f347a55df..17a0b6821d 100644 --- a/vlib/builtin/cfns.c.v +++ b/vlib/builtin/cfns.c.v @@ -132,8 +132,6 @@ fn C.sigemptyset() int fn C.getcwd(buf &char, size size_t) &char -fn C.signal(signal int, handlercb voidptr) voidptr - [trusted] fn C.mktime() int diff --git a/vlib/os/os_c.v b/vlib/os/os_c.v index 55cd5a02c5..8740789815 100644 --- a/vlib/os/os_c.v +++ b/vlib/os/os_c.v @@ -828,12 +828,6 @@ fn normalize_drive_letter(path string) string { return path } -// signal will assign `handler` callback to be called when `signum` signal is received. -pub fn signal(signum int, handler voidptr) voidptr { - res := unsafe { C.signal(signum, handler) } - return res -} - // fork will fork the current system process and return the pid of the fork. pub fn fork() int { mut pid := -1 diff --git a/vlib/os/signal.c.v b/vlib/os/signal.c.v new file mode 100644 index 0000000000..6ae98814cb --- /dev/null +++ b/vlib/os/signal.c.v @@ -0,0 +1,58 @@ +module os + +#include + +pub enum Signal { + hup = 1 + int + quit + ill + trap + abrt + bus + fpe + kill + usr1 + segv + usr2 + pipe + alrm + term + stkflt + chld + cont + stop + tstp + ttin + ttou + urg + xcpu + xfsz + vtalrm + prof + winch + poll + pwr + sys +} + +type SignalHandler = fn (Signal) + +fn C.signal(signal int, handlercb SignalHandler) voidptr + +[deprecated: 'use os.signal_opt() instead'] +[deprecated_after: '2021-05-18'] +pub fn signal(signum int, handler voidptr) voidptr { + return voidptr(signal_opt(Signal(signum), handler) or { C.SIG_ERR }) +} + +// signal will assign `handler` callback to be called when `signum` signal is received. +pub fn signal_opt(signum Signal, handler SignalHandler) ?SignalHandler { + C.errno = 0 + prev_handler := C.signal(int(signum), handler) + if prev_handler == C.SIG_ERR { + // errno isn't correctly set on Windows, but EINVAL is this only possible value it can take anyway + return error_with_code(posix_get_error_msg(C.EINVAL), C.EINVAL) + } + return SignalHandler(prev_handler) +} diff --git a/vlib/os/signal_test.v b/vlib/os/signal_test.v new file mode 100644 index 0000000000..1c56540c81 --- /dev/null +++ b/vlib/os/signal_test.v @@ -0,0 +1,35 @@ +import os + +fn former_handler(signal os.Signal) { + println('former_handler') + exit(0) +} + +fn default_handler(signal os.Signal) { + println('default_handler') + exit(0) +} + +fn test_signal_opt() { + os.signal_opt(.int, default_handler) or { assert false } +} + +fn test_signal_opt_invalid_argument() { + // Can't register a signal on SIGKILL + if _ := os.signal_opt(.kill, default_handler) { + assert false + } + os.signal_opt(.kill, default_handler) or { + assert err.msg == 'Invalid argument' + assert err.code == 22 + } +} + +fn test_signal_opt_return_former_handler() { + func1 := os.signal_opt(.term, former_handler) or { panic('unexpected error') } + assert isnil(func1) + func2 := os.signal_opt(.term, default_handler) or { panic('unexpected error') } + assert !isnil(func2) + // this should work, but makes the CI fail because of a bug in clang -fsanitize=memory + // assert func2 == former_handler +} diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index 2124379e50..f1a1a0714c 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -515,8 +515,6 @@ typedef int (*qsort_callback_func)(const void*, const void*); #endif #endif -//#include "fns.h" -#include #include // for va_list //================================== GLOBALS =================================*/