diff options
author | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2013-07-05 11:46:04 -0400 |
---|---|---|
committer | Andrew J. Schorr <aschorr@telemetry-investments.com> | 2013-07-05 11:46:04 -0400 |
commit | 6b5925f4c303d43228ffe5e37b84d9017d2ff5e3 (patch) | |
tree | d3092723970596cad887a47c171972ac1af5f6fb | |
parent | ad5c8d1f818c96579fa9e7f3c691739e9761e1e7 (diff) | |
download | egawk-6b5925f4c303d43228ffe5e37b84d9017d2ff5e3.tar.gz egawk-6b5925f4c303d43228ffe5e37b84d9017d2ff5e3.tar.bz2 egawk-6b5925f4c303d43228ffe5e37b84d9017d2ff5e3.zip |
Add a kill function to the select extension, and check whether sigprocmask is available.
-rw-r--r-- | extension/ChangeLog | 11 | ||||
-rw-r--r-- | extension/configh.in | 6 | ||||
-rwxr-xr-x | extension/configure | 2 | ||||
-rw-r--r-- | extension/configure.ac | 2 | ||||
-rw-r--r-- | extension/select.c | 63 |
5 files changed, 77 insertions, 7 deletions
diff --git a/extension/ChangeLog b/extension/ChangeLog index efb38249..49c100e4 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,3 +1,14 @@ +2013-07-05 Andrew J. Schorr <aschorr@telemetry-investments.com> + + * configure.ac (AC_CHECK_FUNCS): Add kill and sigprocmask. + * select.c (get_signal_number): Change error messages since now may + be called by "kill" as well as "select_signal". + (do_signal): Add a lint warning if there are more than 2 args. + (do_kill): Add new function to send a signal. + (do_select): Support platforms where sigprocmask is not available. + There will be a race condition on such platforms, but that is not + easily avoided. + 2013-07-02 Andrew J. Schorr <aschorr@telemetry-investments.com> * select.c (do_select): Now that the API flatten_array call has been diff --git a/extension/configh.in b/extension/configh.in index a7212dc1..aa5c71e1 100644 --- a/extension/configh.in +++ b/extension/configh.in @@ -66,6 +66,9 @@ /* Define to 1 if you have the <inttypes.h> header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the `kill' function. */ +#undef HAVE_KILL + /* Define to 1 if you have the <limits.h> header file. */ #undef HAVE_LIMITS_H @@ -84,6 +87,9 @@ /* Define to 1 if you have the <signal.h> header file. */ #undef HAVE_SIGNAL_H +/* Define to 1 if you have the `sigprocmask' function. */ +#undef HAVE_SIGPROCMASK + /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H diff --git a/extension/configure b/extension/configure index 02ff3dc8..c9cb9a28 100755 --- a/extension/configure +++ b/extension/configure @@ -14018,7 +14018,7 @@ done for ac_func in fdopendir fnmatch gettimeofday \ - getdtablesize nanosleep select sigaction \ + getdtablesize kill nanosleep select sigaction sigprocmask \ GetSystemTimeAsFileTime do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` diff --git a/extension/configure.ac b/extension/configure.ac index 5b95f966..aca856a0 100644 --- a/extension/configure.ac +++ b/extension/configure.ac @@ -71,7 +71,7 @@ AC_CHECK_HEADERS(dirent.h fnmatch.h limits.h time.h sys/time.h sys/select.h \ sys/param.h signal.h) AC_CHECK_FUNCS(fdopendir fnmatch gettimeofday \ - getdtablesize nanosleep select sigaction \ + getdtablesize kill nanosleep select sigaction sigprocmask \ GetSystemTimeAsFileTime) GAWK_FUNC_DIRFD diff --git a/extension/select.c b/extension/select.c index 89dbf6c3..261d8ebd 100644 --- a/extension/select.c +++ b/extension/select.c @@ -127,7 +127,7 @@ get_signal_number(awk_value_t signame) case AWK_NUMBER: x = signame.num_value; if ((x != signame.num_value) || ! IS_VALID_SIGNAL(x)) { - update_ERRNO_string(_("select_signal: invalid signal number")); + update_ERRNO_string(_("invalid signal number")); return -1; } return x; @@ -139,10 +139,10 @@ get_signal_number(awk_value_t signame) if ((integer_string(signame.str_value.str, &z) == 0) && IS_VALID_SIGNAL(z)) return z; } - update_ERRNO_string(_("select_signal: invalid signal name")); + update_ERRNO_string(_("invalid signal name")); return -1; default: - update_ERRNO_string(_("select_signal: signal name argument must be string or numeric")); + update_ERRNO_string(_("signal name argument must be string or numeric")); return -1; } } @@ -157,6 +157,8 @@ do_signal(int nargs, awk_value_t *result) int signum; struct sigaction sa; + if (do_lint && nargs > 2) + lintwarn(ext_id, _("select_signal: called with too many arguments")); if (! get_argument(0, AWK_UNDEFINED, & signame)) { update_ERRNO_string(_("select_signal: missing required signal name argument")); return make_number(-1, result); @@ -190,6 +192,43 @@ do_signal(int nargs, awk_value_t *result) #endif } +/* do_kill --- send a signal */ + +static awk_value_t * +do_kill(int nargs, awk_value_t *result) +{ +#ifdef HAVE_KILL + awk_value_t pidarg, signame; + pid_t pid; + int signum; + int rc; + + if (do_lint && nargs > 2) + lintwarn(ext_id, _("kill: called with too many arguments")); + if (! get_argument(0, AWK_NUMBER, & pidarg)) { + update_ERRNO_string(_("kill: missing required pid argument")); + return make_number(-1, result); + } + pid = pidarg.num_value; + if (pid != pidarg.num_value) { + update_ERRNO_string(_("kill: pid argument must be an integer")); + return make_number(-1, result); + } + if (! get_argument(1, AWK_UNDEFINED, & signame)) { + update_ERRNO_string(_("kill: missing required signal name argument")); + return make_number(-1, result); + } + if ((signum = get_signal_number(signame)) < 0) + return make_number(-1, result); + if ((rc = kill(pid, signum)) < 0) + update_ERRNO_int(errno); + return make_number(rc, result); +#else + update_ERRNO_string(_("kill: not supported on this platform")); + return make_number(-1, result); +#endif +} + /* do_select --- I/O multiplexing */ static awk_value_t * @@ -290,13 +329,26 @@ do_select(int nargs, awk_value_t *result) if (dosig && caught.flag) { int i; - sigset_t set, oldset, trapped; + sigset_t trapped; +#ifdef HAVE_SIGPROCMASK + /* + * Block signals while we copy and reset the mask to eliminate + * a race condition whereby a signal could be missed. + */ + sigset_t set, oldset; sigfillset(& set); sigprocmask(SIG_SETMASK, &set, &oldset); +#endif + /* + * Reset flag to 0 first. If we don't have sigprocmask, + * that may reduce the chance of missing a signal. + */ + caught.flag = 0; trapped = caught.mask; sigemptyset(& caught.mask); - caught.flag = 0; +#ifdef HAVE_SIGPROCMASK sigprocmask(SIG_SETMASK, &oldset, NULL); +#endif /* populate sigarr with trapped signals */ /* * XXX this is very inefficient! Note that get_signal_number @@ -391,6 +443,7 @@ static awk_ext_func_t func_table[] = { { "select", do_select, 5 }, { "select_signal", do_signal, 2 }, { "set_non_blocking", do_set_non_blocking, 2 }, + { "kill", do_kill, 2 }, }; /* define the dl_load function using the boilerplate macro */ |