aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extension/ChangeLog11
-rw-r--r--extension/configh.in6
-rwxr-xr-xextension/configure2
-rw-r--r--extension/configure.ac2
-rw-r--r--extension/select.c63
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 */