From 508125f959419cc6d7dceb500e49189bfc224984 Mon Sep 17 00:00:00 2001 From: WaLyong Cho Date: Tue, 8 Nov 2016 13:24:37 +0900 Subject: [PATCH] libsystem: exec: kill child on timeout and add kill signal selectable api On timeout, in do_fork_exec_redirect() ordo_fork_exec(), kill the child process with SIGTERM signal. And to configure the kill signal add new two api. - do_fork_exec_kill() - do_fork_exec_kill_redirect() Change-Id: I3877881a98ecc1a86b37ce045443b7e85e3569fa Signed-off-by: WaLyong Cho --- src/libsystem/exec.c | 27 +++++++++-- src/libsystem/libsystem.h | 97 ++++++++++++++++++++++++++++++++++----- 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/src/libsystem/exec.c b/src/libsystem/exec.c index 272014d..5fb49f4 100644 --- a/src/libsystem/exec.c +++ b/src/libsystem/exec.c @@ -29,10 +29,11 @@ #include #include #include +#include #include "libsystem.h" -static int wait_child(pid_t pid, int64_t timeout_msec) { +static int wait_child(pid_t pid, int64_t timeout_msec, int sig) { struct timeval start, timeout; int status; @@ -62,8 +63,10 @@ static int wait_child(pid_t pid, int64_t timeout_msec) { timersub(¤t, &start, &delta); - if (timercmp(&timeout, &delta, <)) + if (timercmp(&timeout, &delta, <)) { + (void) kill(pid, sig); return -ETIME; + } usleep(100000); } @@ -71,7 +74,7 @@ static int wait_child(pid_t pid, int64_t timeout_msec) { return WEXITSTATUS(status); } -int do_fork_exec_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int fd, int flags) { +int do_fork_exec_kill_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int sig, int fd, int flags) { pid_t pid; assert(argv); @@ -97,12 +100,26 @@ int do_fork_exec_redirect(char *const argv[], char * const envp[], int64_t timeo _exit(EXIT_FAILURE); } - return wait_child(pid, timeout_msec); + return wait_child(pid, timeout_msec, sig); +} + +int do_fork_exec_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int fd, int flags) { + + assert(argv); + + return do_fork_exec_kill_redirect(argv, envp, timeout_msec, SIGTERM, fd, flags); +} + +int do_fork_exec_kill(char *const argv[], char * const envp[], int64_t timeout_msec, int sig) { + + assert(argv); + + return do_fork_exec_kill_redirect(argv, envp, timeout_msec, sig, -1, EXEC_REDIRECT_NONE); } int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec) { assert(argv); - return do_fork_exec_redirect(argv, envp, timeout_msec, -1, EXEC_REDIRECT_NONE); + return do_fork_exec_kill(argv, envp, timeout_msec, SIGTERM); } diff --git a/src/libsystem/libsystem.h b/src/libsystem/libsystem.h index 18220f6..096b849 100644 --- a/src/libsystem/libsystem.h +++ b/src/libsystem/libsystem.h @@ -809,12 +809,38 @@ bool mnt_is_mounted(const char *fsname, const char *dir, const char *type, const */ /** - * @brief Traditional fork() and exec() helper. + * standard output/error redirect flags + */ +enum { + /** + * Do not redirect standard output/error + */ + EXEC_REDIRECT_NONE = 0x01 << 0, + /** + * Redirect standard output only + */ + EXEC_REDIRECT_OUTPUT = 0x01 << 1, + /** + * Redirect standard error only + */ + EXEC_REDIRECT_ERROR = 0x01 << 2, + /** + * Redirect standard output and error all + */ + EXEC_REDIRECT_ALL = (EXEC_REDIRECT_OUTPUT | EXEC_REDIRECT_ERROR), +}; + +/** + * @brief Traditional fork() and exec() helper. If child is not + * deactivated within given \p timeout_msec then kill it with given + * signal. And additionally redirect child process standard output or + * standard error to given fd. * * @param argv array of pointers to null-terminated strings that * represent the argument list available to the new program. The first * argument should point to the filename associated with the file - * being executed. The array of pointers must be terminated by a NULL pointer. + * being executed. The array of pointers must be terminated by a NULL + * pointer. * @param envp specify the environment of the executed program via the * argument envp. The envp argument is an array of pointers to * null-terminated strings and must be terminated by a NULL pointer. @@ -825,19 +851,17 @@ bool mnt_is_mounted(const char *fsname, const char *dir, const char *type, const * is given parent will wait given milliseconds and expired return * -1. If the child is exit within the tiemout millisecond return with * child exit code. + * @param sig signal to kill the child on timeout. + * @param fd file descriptor to redirect child standard output or + * error. + * @param flags redirect flag. This flags is able to include + * EXEC_REDIRECT_OUTPUT or EXEC_REDIRECT_ERROR. * * @return exit code of child. It is fully depend on the child * process. If the child exit with 1 then this function also return 1. * Negative errno on error. -ETIME on timer expired. */ -int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec); - -enum { - EXEC_REDIRECT_NONE = 0x01 << 0, - EXEC_REDIRECT_OUTPUT = 0x01 << 1, - EXEC_REDIRECT_ERROR = 0x01 << 2, - EXEC_REDIRECT_ALL = (EXEC_REDIRECT_OUTPUT | EXEC_REDIRECT_ERROR), -}; +int do_fork_exec_kill_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int sig, int fd, int flags); /** * @brief Traditional fork() and exec() helper. And additionally @@ -859,7 +883,7 @@ enum { * child exit code. * @param fd file descriptor to redirect child standard output or error. * @param flags redirect flag. This flags is able to include - * #EXEC_REDIRECT_OUTPUT or EXEC_REDIRECT_ERROR. + * EXEC_REDIRECT_OUTPUT or EXEC_REDIRECT_ERROR. * * @return exit code of child. It is fully depend on the child * process. If the child exit with 1 then this function also return 1. @@ -867,6 +891,57 @@ enum { */ int do_fork_exec_redirect(char *const argv[], char * const envp[], int64_t timeout_msec, int fd, int flags); +/** + * @brief Traditional fork() and exec() helper. If child is not + * deactivated within given \p timeout_msec then kill it with given + * signal. + * + * @param argv array of pointers to null-terminated strings that + * represent the argument list available to the new program. The first + * argument should point to the filename associated with the file + * being executed. The array of pointers must be terminated by a NULL pointer. + * @param envp specify the environment of the executed program via the + * argument envp. The envp argument is an array of pointers to + * null-terminated strings and must be terminated by a NULL pointer. + * @param timeout_msec timeout millisecond to prevent infinite + * waiting. If negative is given, the parent will not wait the + * child. In other word, the parent will return immediately. If 0 is + * given, parent will wait the child infinitly. And if positive value + * is given parent will wait given milliseconds and expired return + * -1. If the child is exit within the tiemout millisecond return with + * child exit code. + * @param sig signal to kill the child on timeout. + * + * @return exit code of child. It is fully depend on the child + * process. If the child exit with 1 then this function also return 1. + * Negative errno on error. -ETIME on timer expired. + */ +int do_fork_exec_kill(char *const argv[], char * const envp[], int64_t timeout_msec, int sig); + +/** + * @brief Traditional fork() and exec() helper. + * + * @param argv array of pointers to null-terminated strings that + * represent the argument list available to the new program. The first + * argument should point to the filename associated with the file + * being executed. The array of pointers must be terminated by a NULL pointer. + * @param envp specify the environment of the executed program via the + * argument envp. The envp argument is an array of pointers to + * null-terminated strings and must be terminated by a NULL pointer. + * @param timeout_msec timeout millisecond to prevent infinite + * waiting. If negative is given, the parent will not wait the + * child. In other word, the parent will return immediately. If 0 is + * given, parent will wait the child infinitly. And if positive value + * is given parent will wait given milliseconds and expired return + * -1. If the child is exit within the tiemout millisecond return with + * child exit code. + * + * @return exit code of child. It is fully depend on the child + * process. If the child exit with 1 then this function also return 1. + * Negative errno on error. -ETIME on timer expired. + */ +int do_fork_exec(char *const argv[], char * const envp[], int64_t timeout_msec); + /** * @} */ -- 2.34.1