-/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2007, 2008, 2009, 2011, 2013 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
#include <stdio.h>
#include <errno.h>
-#include "libguile/_scm.h"
-
-#include "libguile/async.h"
-#include "libguile/eval.h"
-#include "libguile/root.h"
-#include "libguile/vectors.h"
-#include "libguile/threads.h"
-
-#include "libguile/validate.h"
-#include "libguile/scmsigs.h"
-
-#ifdef HAVE_IO_H
-#include <io.h> /* for mingw _pipe() */
-#endif
-
#ifdef HAVE_PROCESS_H
#include <process.h> /* for mingw */
#endif
#include <sys/time.h>
#endif
-#ifdef __MINGW32__
-#include <windows.h>
-#define alarm(sec) (0)
-/* This weird comma expression is because Sleep is void under Windows. */
-#define sleep(sec) (Sleep ((sec) * 1000), 0)
-#define usleep(usec) (Sleep ((usec) / 1000), 0)
-#define pipe(fd) _pipe (fd, 256, O_BINARY)
-#endif
-
#include <full-write.h>
+#include "libguile/_scm.h"
+
+#include "libguile/async.h"
+#include "libguile/eval.h"
+#include "libguile/root.h"
+#include "libguile/vectors.h"
+#include "libguile/threads.h"
+
+#include "libguile/validate.h"
+#include "libguile/scmsigs.h"
+
\f
#endif
}
+struct signal_pipe_data
+{
+ char sigbyte;
+ ssize_t n;
+ int err;
+};
+
+#ifndef HAVE_GC_GET_SUSPEND_SIGNAL
+static int
+GC_get_suspend_signal (void)
+{
+#if defined SIG_SUSPEND
+ return SIG_SUSPEND;
+#elif defined SIGPWR
+ return SIGPWR;
+#elif defined SIGLOST
+ return SIGLOST;
+#elif defined _SIGRTMIN
+ return _SIGRTMIN + 6;
+#elif defined SIGRTMIN
+ return SIGRTMIN + 6;
+#elif defined __GLIBC__
+ return 32+6;
+#else
+ return SIGUSR1;
+#endif
+}
+#endif /* HAVE_GC_GET_SUSPEND_SIGNAL */
+
+static void*
+read_signal_pipe_data (void * data)
+{
+ struct signal_pipe_data *sdata = data;
+
+ sdata->n = read (signal_pipe[0], &sdata->sigbyte, 1);
+ sdata->err = errno;
+
+ return NULL;
+}
+
static SCM
signal_delivery_thread (void *data)
{
- int n, sig;
- char sigbyte;
+ int sig;
#if HAVE_PTHREAD_SIGMASK /* not on mingw, see notes above */
sigset_t all_sigs;
sigfillset (&all_sigs);
+ /* On libgc 7.1 and earlier, GC_do_blocking doesn't actually do
+ anything. So in that case, libgc will want to suspend the signal
+ delivery thread, so we need to allow it to do so by unmasking the
+ suspend signal. */
+ sigdelset (&all_sigs, GC_get_suspend_signal ());
scm_i_pthread_sigmask (SIG_SETMASK, &all_sigs, NULL);
#endif
while (1)
{
- n = read (signal_pipe[0], &sigbyte, 1);
- sig = sigbyte;
- if (n == 1 && sig >= 0 && sig < NSIG)
+ struct signal_pipe_data sigdata;
+
+ scm_without_guile (read_signal_pipe_data, &sigdata);
+
+ sig = sigdata.sigbyte;
+ if (sigdata.n == 1 && sig >= 0 && sig < NSIG)
{
SCM h, t;
if (scm_is_true (h))
scm_system_async_mark_for_thread (h, t);
}
- else if (n == 0)
+ else if (sigdata.n == 0)
break; /* the signal pipe was closed. */
- else if (n < 0 && errno != EINTR)
+ else if (sigdata.n < 0 && sigdata.err != EINTR)
perror ("error in signal delivery thread");
}
scm_i_pthread_mutex_lock (&signal_delivery_thread_mutex);
- if (pipe (signal_pipe) != 0)
+ if (pipe2 (signal_pipe, O_CLOEXEC) != 0)
scm_syserror (NULL);
signal_thread = scm_spawn_thread (signal_delivery_thread, NULL,
scm_handle_by_message,
install_handler (csig, SCM_BOOL_F, SCM_BOOL_F);
}
else
- SCM_OUT_OF_RANGE (2, handler);
+ {
+ SCM_CRITICAL_SECTION_END;
+ SCM_OUT_OF_RANGE (2, handler);
+ }
}
else if (scm_is_false (handler))
{
}
#undef FUNC_NAME
+#if defined HAVE_ALARM && HAVE_DECL_ALARM
SCM_DEFINE (scm_alarm, "alarm", 1, 0, 0,
(SCM i),
"Set a timer to raise a @code{SIGALRM} signal after the specified\n"
return scm_from_uint (alarm (scm_to_uint (i)));
}
#undef FUNC_NAME
+#endif /* HAVE_ALARM */
#ifdef HAVE_SETITIMER
SCM_DEFINE (scm_setitimer, "setitimer", 5, 0, 0,
signal_handlers =
SCM_VARIABLE_LOC (scm_c_define ("signal-handlers",
scm_c_make_vector (NSIG, SCM_BOOL_F)));
- signal_handler_asyncs =
- scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
- signal_handler_threads =
- scm_permanent_object (scm_c_make_vector (NSIG, SCM_BOOL_F));
+ signal_handler_asyncs = scm_c_make_vector (NSIG, SCM_BOOL_F);
+ signal_handler_threads = scm_c_make_vector (NSIG, SCM_BOOL_F);
for (i = 0; i < NSIG; i++)
{