[INTERPRETER]

* BUG: Tasks do not inherit signal handler pipe anymore, they recreate it instead. Otherwise you have interferences with the parent process of the task, and some signals are lost.
* BUG: Buffered streams now take the internal stream flag "available_now" into account. No idea why that was disabled.
* BUG: Standard streams now set the internal stream flag "available_now" if they are not connected to a terminal. Which may not be necessarily accurate, so it is a temporary change.


git-svn-id: svn://localhost/gambas/trunk@8052 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2017-01-11 16:57:44 +00:00
parent e73d08f2bf
commit 6950a075f0
7 changed files with 109 additions and 41 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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();
}

View file

@ -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

View file

@ -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;

View file

@ -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)