[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:
parent
e73d08f2bf
commit
6950a075f0
7 changed files with 109 additions and 41 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue