about summary refs log tree commit homepage
path: root/sig.c
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-06-21 03:34:25 +0000
committerEric Wong <normalperson@yhbt.net>2013-06-25 21:33:57 +0000
commit07569135228020880d8092d9aaf7d6325cc48d26 (patch)
treebd3716776e146bd41e4b8510875f043a02a0ac7b /sig.c
parentba8a3673a6ada7122c89e420455901b6b1288500 (diff)
downloadcmogstored-07569135228020880d8092d9aaf7d6325cc48d26.tar.gz
Cancellation with epoll_wait, accept4 (and accept) may cause events
to be lost, as cancellation relies on signals anyways in glibc/Linux.

So instead, we use signaling ourselves and explicitly test for
cancellation only if we know we are interrupted and in a state where
a thread can safely be cancelled.

ref: http://mid.gmane.org/CAE2sS1gxQkqmcywQ07pmgNHM+CyqzMkuASVjmWDL+hgaTMURWQ@mail.gmail.com
Diffstat (limited to 'sig.c')
-rw-r--r--sig.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/sig.c b/sig.c
index f0feb32..8c052f6 100644
--- a/sig.c
+++ b/sig.c
@@ -9,12 +9,27 @@
  */
 
 static sigset_t fullset;
+static sigset_t cancelset;
 sigset_t mog_emptyset;
 
 __attribute__((constructor)) void sig_init(void)
 {
         CHECK(int, 0, sigfillset(&fullset));
         CHECK(int, 0, sigemptyset(&mog_emptyset));
+        CHECK(int, 0, sigfillset(&cancelset));
+        CHECK(int, 0, sigdelset(&cancelset, SIGURG));
+}
+
+/* this runs at the start of every thread managed by thrpool */
+void mog_cancel_prepare(void)
+{
+        int old;
+
+        CHECK(int, 0, pthread_sigmask(SIG_SETMASK, &cancelset, NULL));
+        mog_cancel_disable();
+        CHECK(int, 0, pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old));
+        assert(old == PTHREAD_CANCEL_DEFERRED
+               && "async cancel enabled redundantly");
 }
 
 void mog_intr_disable(void)