[m-rev.] for review: Handle sem_wait, sem_timedwait being interrupted by signal handlers.
Peter Wang
novalazy at gmail.com
Wed Jul 5 17:05:37 AEST 2017
sem_wait or sem_timedwait may be interrupted by signal handlers and
return an error. We must retry the call if errno is set to EINTR.
library/thread.m:
Retry MR_SEM_WAIT if interrupted by a signal handler in
ML_create_exclusive_thread.
Call MR_fatal_error if MR_SEM_WAIT fails for any other reason.
The only other documented error code is EINVAL if the semaphore is
invalid; that should not happen.
runtime/mercury_context.c:
Retry MR_SEM_WAIT if interrupted by a signal handler in
MR_shutdown_ws_engines.
runtime/mercury_thread.h:
Add the macro MR_SEM_IS_EINTR for checking if errno == EINTR
after calling MR_SEM_WAIT or MR_SEM_TIMED_WAIT.
---
library/thread.m | 17 +++++++++++++----
runtime/mercury_context.c | 6 +++++-
runtime/mercury_thread.h | 9 ++++++++-
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/library/thread.m b/library/thread.m
index 0d80e9b..4cfec3a 100644
--- a/library/thread.m
+++ b/library/thread.m
@@ -536,7 +536,7 @@ INIT mercury_sys_init_thread_modules
ML_ThreadWrapperArgs args;
pthread_t thread;
pthread_attr_t attrs;
- int err;
+ int thread_err;
ML_incr_thread_barrier_count();
@@ -549,11 +549,20 @@ INIT mercury_sys_init_thread_modules
pthread_attr_init(&attrs);
pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);
- err = pthread_create(&thread, &attrs, ML_exclusive_thread_wrapper, &args);
+ thread_err = pthread_create(&thread, &attrs, ML_exclusive_thread_wrapper, &args);
pthread_attr_destroy(&attrs);
- if (err == 0) {
- MR_SEM_WAIT(&args.sem, ""ML_create_exclusive_thread"");
+ if (thread_err == 0) {
+ int sem_err;
+
+ do {
+ sem_err = MR_SEM_WAIT(&args.sem, ""ML_create_exclusive_thread"");
+ } while (sem_err == -1 && MR_SEM_IS_EINTR(errno));
+
+ if (sem_err != 0) {
+ MR_fatal_error(
+ ""ML_create_exclusive_thread: MR_SEM_WAIT error %d"", errno);
+ }
}
MR_sem_destroy(&args.sem);
diff --git a/runtime/mercury_context.c b/runtime/mercury_context.c
index ee1f6db..8bad7c9 100644
--- a/runtime/mercury_context.c
+++ b/runtime/mercury_context.c
@@ -1996,7 +1996,11 @@ MR_shutdown_ws_engines(void)
}
for (i = 0; i < (MR_num_ws_engines - 1); i++) {
- MR_SEM_WAIT(&shutdown_ws_semaphore, "MR_shutdown_ws_engines");
+ int err;
+
+ do {
+ err = MR_SEM_WAIT(&shutdown_ws_semaphore, "MR_shutdown_ws_engines");
+ } while (err == -1 && MR_SEM_IS_EINTR(errno));
}
}
diff --git a/runtime/mercury_thread.h b/runtime/mercury_thread.h
index 32de40d..288abe7 100644
--- a/runtime/mercury_thread.h
+++ b/runtime/mercury_thread.h
@@ -74,13 +74,18 @@
// generated code is considered stable, since the alternative versions do
// the same thing, but with debugging support enabled.
+ // MR_SEM_IS_EINTR is used to test if MR_SEM_WAIT or MR_SEM_TIMED_WAIT was
+ // interrupted by a signal. We do not test errno when using libdispatch as
+ // the manual page for dispatch_semaphore_wait does not mention errno nor
+ // EINTR.
+
#define MR_LOCK(lck, from) pthread_mutex_lock((lck))
#define MR_UNLOCK(lck, from) pthread_mutex_unlock((lck))
#define MR_COND_SIGNAL(cnd, from) pthread_cond_signal((cnd))
#define MR_COND_BROADCAST(cnd, from) pthread_cond_broadcast((cnd))
#define MR_COND_WAIT(cnd, mtx, from) pthread_cond_wait((cnd), (mtx))
- #define MR_COND_TIMED_WAIT(cond, mtx, abstime, from) \
+ #define MR_COND_TIMED_WAIT(cond, mtx, abstime, from) \
pthread_cond_timedwait((cond), (mtx), (abstime))
#if defined(MR_USE_LIBDISPATCH)
@@ -89,11 +94,13 @@
#define MR_SEM_POST(sem, from) dispatch_semaphore_signal(*(sem))
#define MR_SEM_TIMED_WAIT(sem, abstime, from) \
dispatch_semaphore_wait(*(sem), dispatch_walltime((abstime), 0))
+ #define MR_SEM_IS_EINTR(errno) MR_FALSE
#else
#define MR_SEM_WAIT(sem, from) sem_wait((sem))
#define MR_SEM_POST(sem, from) sem_post((sem))
#define MR_SEM_TIMED_WAIT(sem, abstime, from) \
sem_timedwait((sem), (abstime))
+ #define MR_SEM_IS_EINTR(errno) (errno == EINTR)
#endif // !MR_USE_LIBDISPATCH
#else // MR_DEBUG_THREADS
--
2.9.0
More information about the reviews
mailing list