From b3f8bee89e3fa5713ff391e0172b8e1d4b92be25 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 12 Dec 2013 22:47:27 -0800 Subject: First cut at signal handling support. * Makefile (OBJS-y): Include signal.o if have_posix_sigs is "y". * configure (have_posix_sigs): New variable, set by detecting POSIX signal stuff. * dep.mk: Regenerated. * arith.c, debug.c, eval.c, filter.c, hash.c, match.c, parser.y, parser.l, rand.c, regex.c, syslog.c, txr.c, utf8.c: Include new signal.h header, now required by unwind, and the system header. * eval.c (exit_wrap): New function. (eval_init): New functions registered as intrinsics: exit_wrap, set_sig_handler, get_sig_handler, sig_check. * gc.c (release): Unused functions removed. * gc.h (release): Declaration removed. * lib.c (init): Call sig_init. * stream.c (set_putc, se_getc, se_fflush): New static functions. (stdio_put_char_callback, stdio_get_char_callback, stdio_put_byte, stdio_flush, stdio_get_byte): Use new functions to enable signals when blocked on I/O. (tail_strategy): Allow signals across sleep. (pipev_close): Allow signals across waitpid. (se_pclose): New static function. (pipe_close): Use new function to enable signals across pclose. * unwind.c (uw_unwind_to_exit_point): use extended_longjmp instead of longjmp. * unwind.h (struct uw_block, struct uw_catch): jb member changes from jmp_buf to extended_jmp_buf. (uw_block_begin, uw_simple_catch_begin, uw_catch_begin): Use extended_setjmp instead of setjmp. * signal.c: New file. * signal.h: New file. --- stream.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 7 deletions(-) (limited to 'stream.c') diff --git a/stream.c b/stream.c index e5e43ac6..5a5d3f74 100644 --- a/stream.c +++ b/stream.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "config.h" #if HAVE_UNISTD_H #include @@ -46,6 +47,7 @@ #endif #include "lib.h" #include "gc.h" +#include "signal.h" #include "unwind.h" #include "stream.h" #include "utf8.h" @@ -157,14 +159,42 @@ static val stdio_maybe_error(val stream, val action) stream, action, num(errno), string_utf8(strerror(errno)), nao); } +static int se_putc(int ch, FILE *f) +{ + int ret; + sig_save_enable; + ret = putc(ch, f); + sig_restore_enable; + return ret; +} + +static int se_getc(FILE *f) +{ + int ret; + sig_save_enable; + ret = getc(f); + sig_restore_enable; + return ret; +} + +static int se_fflush(FILE *f) +{ + int ret; + sig_save_enable; + ret = fflush(f); + sig_restore_enable; + return ret; +} + static int stdio_put_char_callback(int ch, mem_t *f) { - return putc(ch, (FILE *) f) != EOF; + int ret = se_putc(ch, (FILE *) f) != EOF; + return ret; } static int stdio_get_char_callback(mem_t *f) { - return getc((FILE *) f); + return se_getc((FILE *) f); } static val stdio_put_string(val stream, val str) @@ -204,14 +234,14 @@ static val stdio_put_byte(val stream, int b) if (stream != std_debug && stream != std_error) output_produced = t; - return h->f != 0 && putc(b, (FILE *) h->f) != EOF + return h->f != 0 && se_putc(b, (FILE *) h->f) != EOF ? t : stdio_maybe_error(stream, lit("writing")); } static val stdio_flush(val stream) { struct stdio_handle *h = (struct stdio_handle *) stream->co.handle; - return (h->f != 0 && fflush(h->f) == 0) + return (h->f != 0 && se_fflush(h->f) == 0) ? t : stdio_maybe_error(stream, lit("flushing")); } @@ -313,7 +343,7 @@ static val stdio_get_byte(val stream) { struct stdio_handle *h = (struct stdio_handle *) stream->co.handle; if (h->f) { - int ch = getc(h->f); + int ch = se_getc(h->f); return (ch != EOF) ? num(ch) : stdio_maybe_read_error(stream); } return stdio_maybe_read_error(stream); @@ -384,7 +414,9 @@ static void tail_strategy(val stream, unsigned long *state) FILE *newf; if (!(newf = w_freopen(c_str(h->descr), c_str(h->mode), h->f))) { tail_calc(state, &sec, &mod); + sig_save_enable; sleep(sec); + sig_restore_enable; continue; } h->f = newf; @@ -465,21 +497,32 @@ static int pipevp_close(FILE *f, pid_t pid) { int status; fclose(f); + sig_save_enable; while (waitpid(pid, &status, 0) == -1 && errno == EINTR) ; + sig_restore_enable; return status; } #endif +static int se_pclose(FILE *f) +{ + int ret; + sig_save_enable; + ret = pclose(f); + sig_restore_enable; + return ret; +} + static val pipe_close(val stream, val throw_on_error) { struct stdio_handle *h = (struct stdio_handle *) stream->co.handle; if (h->f != 0) { #if HAVE_FORK_STUFF - int status = h->pid != 0 ? pipevp_close(h->f, h->pid) : pclose(h->f); + int status = h->pid != 0 ? pipevp_close(h->f, h->pid) : se_pclose(h->f); #else - int status = pclose(h->f); + int status = se_pclose(h->f); #endif h->f = 0; -- cgit v1.2.3