diff --git a/main/gbx/gbx_c_file.c b/main/gbx/gbx_c_file.c index fa16310aa..dd5983baf 100644 --- a/main/gbx/gbx_c_file.c +++ b/main/gbx/gbx_c_file.c @@ -126,10 +126,12 @@ static CFILE *create_default_stream(FILE *file, int mode) { CFILE *ob; STREAM stream; + bool tty = isatty(fileno(file)); CLEAR(&stream); stream.type = &STREAM_buffer; - stream.common.available_now = !isatty(fileno(file)); + stream.common.available_now = !tty; + stream.common.no_read_ahead = tty; stream.common.standard = TRUE; stream.buffer.file = file; STREAM_check_blocking(&stream); diff --git a/main/gbx/gbx_c_process.c b/main/gbx/gbx_c_process.c index 5cbc99ff4..1896c5517 100644 --- a/main/gbx/gbx_c_process.c +++ b/main/gbx/gbx_c_process.c @@ -963,7 +963,13 @@ void CPROCESS_wait_for(CPROCESS *process, int timeout) { while (process->running) { + #ifdef DEBUG_ME + fprintf(stderr, "Watch process %d\n", process->pid); + #endif ret = WATCH_process(sigfd, process->out, timeout); + #ifdef DEBUG_ME + fprintf(stderr, "Watch process %d -> %d\n", process->pid, ret); + #endif if (ret & WP_OUTPUT) callback_write(process->out, GB_WATCH_READ, process); diff --git a/main/gbx/gbx_c_task.c b/main/gbx/gbx_c_task.c index 8f2a5225b..238bcc187 100644 --- a/main/gbx/gbx_c_task.c +++ b/main/gbx/gbx_c_task.c @@ -98,6 +98,8 @@ static void has_forked(void) stream->common.eol = 0; STREAM_blocking(stream, TRUE); + SIGNAL_has_forked(); + task = _task_list; while (task) { @@ -116,6 +118,10 @@ static void callback_child(int signum, intptr_t data) CTASK *_object, *next; int status; + #if DEBUG_ME + fprintf(stderr, ">> callback_child\n"); + #endif + _object = _task_list; while (_object) { @@ -127,6 +133,10 @@ static void callback_child(int signum, intptr_t data) } _object = next; } + + #if DEBUG_ME + fprintf(stderr, "<< callback_child\n"); + #endif } static int get_readable(int fd) @@ -287,12 +297,15 @@ static bool start_task(CTASK *_object) if (pid == (-1)) { stop_task(THIS); - sigprocmask(SIG_SETMASK, &old, &sig); + sigprocmask(SIG_SETMASK, &old, NULL); goto __ERROR; } if (pid) { + #if DEBUG_ME + fprintf(stderr, "start_task: %p %d\n", THIS, pid); + #endif THIS->pid = pid; if (has_read) @@ -312,14 +325,14 @@ static bool start_task(CTASK *_object) GB_Watch(THIS->fd_err, GB_WATCH_READ, (void *)callback_error, (intptr_t)THIS); } - sigprocmask(SIG_SETMASK, &old, &sig); + sigprocmask(SIG_SETMASK, &old, NULL); } else // child task { THIS->child = TRUE; THIS->pid = getpid(); - sigprocmask(SIG_SETMASK, &old, &sig); + sigprocmask(SIG_SETMASK, &old, NULL); if (has_read) { @@ -425,7 +438,9 @@ static void stop_task(CTASK *_object) int len; GB_RAISE_HANDLER handler; - //printf("stop_task: %p\n", THIS); fflush(stdout); + #if DEBUG_ME + fprintf(stderr, "stop_task: %p %d\n", THIS, THIS->pid); + #endif THIS->stopped = TRUE; diff --git a/main/gbx/gbx_signal.c b/main/gbx/gbx_signal.c index c288c1e64..a3d0e1a24 100644 --- a/main/gbx/gbx_signal.c +++ b/main/gbx/gbx_signal.c @@ -39,7 +39,7 @@ void SIGNAL_install(SIGNAL_HANDLER *handler, int signum, void (*callback)(int, s { struct sigaction action; - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_install: %d %p\n", signum, callback); #endif @@ -55,7 +55,7 @@ void SIGNAL_install(SIGNAL_HANDLER *handler, int signum, void (*callback)(int, s void SIGNAL_uninstall(SIGNAL_HANDLER *handler, int signum) { - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_uninstall: %d\n", signum); #endif @@ -144,7 +144,7 @@ static void purge_callbacks(void) if (_raising_callback) return; - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, ">> purge_callbacks\n"); #endif @@ -155,7 +155,7 @@ static void purge_callbacks(void) cb = _purge_handler->callbacks; while (cb) { - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "purge_callbacks: cb = %p\n", cb); #endif next_cb = cb->next; @@ -167,7 +167,7 @@ static void purge_callbacks(void) } } - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "<< purge_callbacks\n"); #endif } @@ -177,17 +177,32 @@ void SIGNAL_raise_callbacks(int fd, int type, void *data) SIGNAL_HANDLER *handler; SIGNAL_CALLBACK *cb; char signum; + int ret; /*old = signal(SIGCHLD, signal_child);*/ + #if DEBUG_ME + fprintf(stderr, "SIGNAL_raise_callbacks: fd = %d blocking = %d\n", fd, (fcntl(fd, F_GETFL) & O_NONBLOCK) == 0); + #endif - if (read(fd, &signum, 1) != 1) + ret = read(fd, &signum, 1); + if (ret != 1) + { + #if DEBUG_ME + fprintf(stderr, "SIGNAL_raise_callbacks: read -> %d / errno = %d\n", ret, errno); + #endif return; + } handler = find_handler(signum); if (!handler) + { + #if DEBUG_ME + fprintf(stderr, "SIGNAL_raise_callbacks: no handler\n"); + #endif return; + } - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, ">> SIGNAL_raise_callbacks (%d)\n", _raising_callback); #endif @@ -200,7 +215,7 @@ void SIGNAL_raise_callbacks(int fd, int type, void *data) cb = handler->callbacks; while (cb) { - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_raise_callbacks: cb = %p cb->callback = %p\n", cb, cb->callback); #endif if (cb->callback) @@ -211,33 +226,55 @@ void SIGNAL_raise_callbacks(int fd, int type, void *data) } END_ERROR - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_raise_callbacks: purge_callbacks\n"); #endif purge_callbacks(); - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "<< SIGNAL_raise_callbacks (%d)\n", _raising_callback); #endif } +static void create_pipe(void) +{ + if (pipe(_pipe) != 0) + ERROR_panic("Cannot create signal handler pipes: %s", strerror(errno)); + + if (_pipe[0] == 0) + BREAKPOINT(); + + fcntl(_pipe[0], F_SETFD, FD_CLOEXEC); + fcntl(_pipe[1], F_SETFD, FD_CLOEXEC); + // Allows to read the signal pipe without blocking + fcntl(_pipe[0], F_SETFL, fcntl(_pipe[0], F_GETFL) | O_NONBLOCK); + + GB_Watch(_pipe[0], GB_WATCH_READ, (void *)SIGNAL_raise_callbacks, 0); + + #if DEBUG_ME + fprintf(stderr, "create_pipe: fd = %d\n", _pipe[0]); + #endif +} + +static void delete_pipe(void) +{ + #if DEBUG_ME + fprintf(stderr, "delete_pipe: fd = %d\n", _pipe[0]); + #endif + GB_Watch(_pipe[0], GB_WATCH_NONE, NULL, 0); + close(_pipe[0]); + close(_pipe[1]); + _pipe[0] = -1; + _pipe[1] = -1; +} + SIGNAL_CALLBACK *SIGNAL_register(int signum, void (*callback)(int, intptr_t), intptr_t data) { SIGNAL_HANDLER *handler; SIGNAL_CALLBACK *cb; if (!_count) - { - if (pipe(_pipe) != 0) - ERROR_panic("Cannot create signal handler pipes: %s", strerror(errno)); - - fcntl(_pipe[0], F_SETFD, FD_CLOEXEC); - fcntl(_pipe[1], F_SETFD, FD_CLOEXEC); - // Allows to read the signal pipe without blocking - fcntl(_pipe[0], F_SETFL, fcntl(_pipe[0], F_GETFL) | O_NONBLOCK); - - GB_Watch(_pipe[0], GB_WATCH_READ, (void *)SIGNAL_raise_callbacks, 0); - } + create_pipe(); _count++; @@ -259,11 +296,11 @@ SIGNAL_CALLBACK *SIGNAL_register(int signum, void (*callback)(int, intptr_t), in cb->next->prev = cb; handler->callbacks = cb; - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_register: %d -> %p (%p)\n", signum, cb, cb->callback); #endif - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "handler->callbacks %p:", handler); SIGNAL_CALLBACK *save = cb; cb = handler->callbacks; @@ -288,7 +325,7 @@ void SIGNAL_unregister(int signum, SIGNAL_CALLBACK *cb) if (_raising_callback) { - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_unregister: disable %d %p (%p)\n", signum, cb, cb->callback); #endif cb->callback = NULL; @@ -296,7 +333,7 @@ void SIGNAL_unregister(int signum, SIGNAL_CALLBACK *cb) return; } - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "SIGNAL_unregister: remove %d %p (%p)\n", signum, cb, cb->callback); #endif @@ -314,15 +351,9 @@ void SIGNAL_unregister(int signum, SIGNAL_CALLBACK *cb) _count--; if (_count == 0) - { - GB_Watch(_pipe[0], GB_WATCH_NONE, NULL, 0); - close(_pipe[0]); - close(_pipe[1]); - _pipe[0] = -1; - _pipe[1] = -1; - } + delete_pipe(); - #ifdef DEBUG_ME + #if DEBUG_ME fprintf(stderr, "handler->callbacks %p:", handler); cb = handler->callbacks; while (cb) @@ -355,3 +386,14 @@ int SIGNAL_get_fd(void) { return _pipe[0]; } + +void SIGNAL_has_forked(void) +{ + if (!_count) + return; + + GB_Watch(_pipe[0], GB_WATCH_NONE, NULL, 0); + close(_pipe[0]); + close(_pipe[1]); + create_pipe(); +} diff --git a/main/gbx/gbx_signal.h b/main/gbx/gbx_signal.h index f4223bfa6..1551e3714 100644 --- a/main/gbx/gbx_signal.h +++ b/main/gbx/gbx_signal.h @@ -54,6 +54,7 @@ void SIGNAL_unregister(int signum, SIGNAL_CALLBACK *cb); int SIGNAL_get_fd(void); void SIGNAL_raise_callbacks(int fd, int type, void *data); void SIGNAL_exit(void); +void SIGNAL_has_forked(void); #endif diff --git a/main/gbx/gbx_stream_buffer.c b/main/gbx/gbx_stream_buffer.c index bd4340cca..921324bab 100644 --- a/main/gbx/gbx_stream_buffer.c +++ b/main/gbx/gbx_stream_buffer.c @@ -206,9 +206,9 @@ static int stream_lof(STREAM *stream, int64_t *len) { struct stat info; - //if (!stream->common.available_now) - // return TRUE; - + if (!stream->common.available_now) + return TRUE; + if (fstat(fileno(FD), &info) < 0) return TRUE; diff --git a/main/gbx/gbx_watch.c b/main/gbx/gbx_watch.c index cefb06685..88b5907f3 100644 --- a/main/gbx/gbx_watch.c +++ b/main/gbx/gbx_watch.c @@ -685,6 +685,8 @@ int WATCH_process(int fd_end, int fd_output, int timeout) ret = select(fd_max + 1, &rfd, NULL, NULL, NULL); } + //fprintf(stderr, "WATCH_process: select -> %d [%d] / fd_end -> %d\n", ret, errno, FD_ISSET(fd_end, &rfd)); + if (ret > 0) break; if (errno != EINTR)