[前][次][番号順一覧][スレッド一覧]

ruby-changes:51897

From: normal <ko1@a...>
Date: Mon, 30 Jul 2018 11:28:05 +0900 (JST)
Subject: [ruby-changes:51897] normal:r64111 (trunk): thread_pthread.c (rb_sigwait_sleep): re-fix [Bug #5343] harder

normal	2018-07-30 11:28:00 +0900 (Mon, 30 Jul 2018)

  New Revision: 64111

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64111

  Log:
    thread_pthread.c (rb_sigwait_sleep): re-fix [Bug #5343] harder
    
    We can't always designate a timer thread, so any sleepers must
    also perform ubf wakeups.  Note: a similar change needs to be
    made for rb_thread_fd_select and rb_wait_for_single_fd.
    
    [ruby-core:88088] [Misc #14937] [Bug #5343]

  Modified files:
    trunk/thread.c
    trunk/thread_pthread.c
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 64110)
+++ thread_pthread.c	(revision 64111)
@@ -1613,11 +1613,45 @@ rb_sigwait_sleep(rb_thread_t *th, int si https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1613
 {
     struct pollfd pfd;
 
-    pfd.fd = sigwait_fd;
-    pfd.events = POLLIN;
+    if (ubf_threads_empty()) {
+        pfd.fd = sigwait_fd;
+        pfd.events = POLLIN;
+        (void)ppoll(&pfd, 1, ts, 0);
+        check_signals_nogvl(th, sigwait_fd);
+    }
+    else {
+        static const struct timespec quantum = { 0, TIME_QUANTUM_USEC * 1000 };
+        struct timespec *endp = 0, end, now;
 
-    (void)ppoll(&pfd, 1, ts, 0);
-    check_signals_nogvl(th, sigwait_fd);
+        if (ts) {
+            getclockofday(&end);
+            timespec_add(&end, ts);
+            endp = &end;
+        }
+
+        getclockofday(&now);
+        for (;;) {
+            const struct timespec *tsp = &quantum;
+            struct timespec diff;
+            int n;
+
+            if (endp) {
+                diff = *endp;
+                timespec_sub(&diff, &now);
+                if (timespec_cmp(&diff, tsp) < 0)
+                    tsp = &diff;
+            }
+
+            n = ppoll(&pfd, 1, tsp, 0);
+            check_signals_nogvl(th, sigwait_fd);
+            if (RUBY_VM_INTERRUPTED(th->ec) || n != 0) break;
+
+            if (endp) {
+                getclockofday(&now);
+                if (timespec_cmp(&now, endp) >= 0) break;
+            }
+        }
+    }
 }
 
 static void
Index: thread.c
===================================================================
--- thread.c	(revision 64110)
+++ thread.c	(revision 64111)
@@ -106,6 +106,7 @@ static int rb_threadptr_pending_interrup https://github.com/ruby/ruby/blob/trunk/thread.c#L106
 static const char *thread_status_name(rb_thread_t *th, int detail);
 static void timespec_add(struct timespec *, const struct timespec *);
 static void timespec_sub(struct timespec *, const struct timespec *);
+static int timespec_cmp(const struct timespec *a, const struct timespec *b);
 static int timespec_update_expire(struct timespec *, const struct timespec *);
 static void getclockofday(struct timespec *);
 NORETURN(static void async_bug_fd(const char *mesg, int errno_arg, int fd));

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]