dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH 1/5] net/http: retryable exception is configurable
@ 2015-08-12 19:23 Eric Wong
  2015-08-12 19:23 ` [PATCH 2/5] thread_pthread: eliminate malloc from signal thread list Eric Wong
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Eric Wong @ 2015-08-12 19:23 UTC (permalink / raw)
  To: spew

---
 lib/net/http.rb | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/net/http.rb b/lib/net/http.rb
index 4db69b6..918a680 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -661,6 +661,11 @@ module Net   #:nodoc:
       SSL_IVNAMES.each do |ivname|
         instance_variable_set ivname, nil
       end
+
+      @retryable_exception = [ Net::ReadTimeout, IOError, EOFError,
+        Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, Timeout::Error ]
+      # avoid a dependency on OpenSSL
+      @retryable_exception << OpenSSL::SSL::SSLError if defined?(OpenSSL::SSL)
     end
 
     def inspect
@@ -1452,7 +1457,8 @@ module Net   #:nodoc:
              # avoid a dependency on OpenSSL
              defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError,
              Timeout::Error => exception
-        if count == 0 && IDEMPOTENT_METHODS_.include?(req.method)
+        if count == 0 && IDEMPOTENT_METHODS_.include?(req.method) &&
+           @retryable_exception.any? { |c| c === exception }
           count += 1
           @socket.close if @socket and not @socket.closed?
           D "Conn close because of error #{exception}, and retry"
-- 
EW


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/5] thread_pthread: eliminate malloc from signal thread list
  2015-08-12 19:23 [PATCH 1/5] net/http: retryable exception is configurable Eric Wong
@ 2015-08-12 19:23 ` Eric Wong
  2015-08-12 19:23 ` [PATCH 3/5] improve handling of timer thread shutdown Eric Wong
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Wong @ 2015-08-12 19:23 UTC (permalink / raw)
  To: spew

ccan/list may be used and the list nodes are embedded directly
into the rb_thread_t structure.

Note: double-checked locking from FGLOCK is still possible, but I am
not convinced it is necessary with modern pthreads implementations.
---
 thread_pthread.c | 90 ++++++++++++++++----------------------------------------
 thread_pthread.h |  9 +++++-
 2 files changed, 34 insertions(+), 65 deletions(-)

diff --git a/thread_pthread.c b/thread_pthread.c
index 26fe9ff..4eca11d 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -1122,15 +1122,7 @@ native_sleep(rb_thread_t *th, struct timeval *timeout_tv)
 }
 
 #ifdef USE_SIGNAL_THREAD_LIST
-struct signal_thread_list {
-    rb_thread_t *th;
-    struct signal_thread_list *prev;
-    struct signal_thread_list *next;
-};
-
-static struct signal_thread_list signal_thread_list_anchor = {
-    0, 0, 0,
-};
+static LIST_HEAD(signal_thread_list_head);
 
 #define FGLOCK(lock, body) do { \
     native_mutex_lock(lock); \
@@ -1144,12 +1136,12 @@ static struct signal_thread_list signal_thread_list_anchor = {
 static void
 print_signal_list(char *str)
 {
-    struct signal_thread_list *list =
-      signal_thread_list_anchor.next;
+    rb_thread_t *th;
+
     thread_debug("list (%s)> ", str);
-    while (list) {
-	thread_debug("%p (%p), ", list->th, list->th->thread_id);
-	list = list->next;
+    list_for_each(&signal_thread_list_head, th,
+		  native_thread_data.signal_thread.node) {
+	thread_debug("%p (%p), ", th, th->thread_id);
     }
     thread_debug("\n");
 }
@@ -1158,47 +1150,23 @@ print_signal_list(char *str)
 static void
 add_signal_thread_list(rb_thread_t *th)
 {
-    if (!th->native_thread_data.signal_thread_list) {
-	FGLOCK(&signal_thread_list_lock, {
-	    struct signal_thread_list *list =
-	      malloc(sizeof(struct signal_thread_list));
-
-	    if (list == 0) {
-		fprintf(stderr, "[FATAL] failed to allocate memory\n");
-		exit(EXIT_FAILURE);
-	    }
-
-	    list->th = th;
-
-	    list->prev = &signal_thread_list_anchor;
-	    list->next = signal_thread_list_anchor.next;
-	    if (list->next) {
-		list->next->prev = list;
-	    }
-	    signal_thread_list_anchor.next = list;
-	    th->native_thread_data.signal_thread_list = list;
-	});
-    }
+    FGLOCK(&signal_thread_list_lock, {
+	if (!th->native_thread_data.signal_thread.listed) {
+	    list_add_tail(&signal_thread_list_head,
+			  &th->native_thread_data.signal_thread.node);
+	}
+    });
 }
 
 static void
 remove_signal_thread_list(rb_thread_t *th)
 {
-    if (th->native_thread_data.signal_thread_list) {
-	FGLOCK(&signal_thread_list_lock, {
-	    struct signal_thread_list *list =
-	      (struct signal_thread_list *)
-		th->native_thread_data.signal_thread_list;
-
-	    list->prev->next = list->next;
-	    if (list->next) {
-		list->next->prev = list->prev;
-	    }
-	    th->native_thread_data.signal_thread_list = 0;
-	    list->th = 0;
-	    free(list); /* ok */
-	});
-    }
+    FGLOCK(&signal_thread_list_lock, {
+	if (th->native_thread_data.signal_thread.listed) {
+	    list_del(&th->native_thread_data.signal_thread.node);
+	    th->native_thread_data.signal_thread.listed = 0;
+	}
+    });
 }
 
 static void
@@ -1231,26 +1199,20 @@ ubf_select(void *ptr)
 static void
 ping_signal_thread_list(void)
 {
-    if (signal_thread_list_anchor.next) {
-	FGLOCK(&signal_thread_list_lock, {
-	    struct signal_thread_list *list;
+    FGLOCK(&signal_thread_list_lock, {
+	rb_thread_t *th;
 
-	    list = signal_thread_list_anchor.next;
-	    while (list) {
-		ubf_select_each(list->th);
-		list = list->next;
-	    }
-	});
-    }
+	list_for_each(&signal_thread_list_head, th,
+	              native_thread_data.signal_thread.node) {
+	    ubf_select_each(th);
+	}
+    });
 }
 
 static int
 check_signal_thread_list(void)
 {
-    if (signal_thread_list_anchor.next)
-	return 1;
-    else
-	return 0;
+    return !list_empty(&signal_thread_list_head);
 }
 #else /* USE_SIGNAL_THREAD_LIST */
 #define add_signal_thread_list(th) (void)(th)
diff --git a/thread_pthread.h b/thread_pthread.h
index 24a4af4..dcffd7a 100644
--- a/thread_pthread.h
+++ b/thread_pthread.h
@@ -11,6 +11,8 @@
 #ifndef RUBY_THREAD_PTHREAD_H
 #define RUBY_THREAD_PTHREAD_H
 
+#include "ccan/list/list.h"
+
 #ifdef HAVE_PTHREAD_NP_H
 #include <pthread_np.h>
 #endif
@@ -26,7 +28,12 @@ typedef struct rb_thread_cond_struct {
 } rb_nativethread_cond_t;
 
 typedef struct native_thread_data_struct {
-    void *signal_thread_list;
+    /* Protected by signal_thread_list_lock: */
+    union {
+	unsigned long listed;
+	struct list_node node;
+    } signal_thread;
+
     rb_nativethread_cond_t sleep_cond;
 } native_thread_data_t;
 
-- 
EW


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/5] improve handling of timer thread shutdown
  2015-08-12 19:23 [PATCH 1/5] net/http: retryable exception is configurable Eric Wong
  2015-08-12 19:23 ` [PATCH 2/5] thread_pthread: eliminate malloc from signal thread list Eric Wong
@ 2015-08-12 19:23 ` Eric Wong
  2015-08-12 19:23 ` [PATCH 4/5] digest: remove needless volatile Eric Wong
  2015-08-12 19:23 ` [PATCH 5/5] remove needless volatile from ALLOCV_N + friends Eric Wong
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Wong @ 2015-08-12 19:23 UTC (permalink / raw)
  To: spew

Shutting down the timer thread now always closes pipes to free FDs.
In fact, we close the write ends of the pipes is done in the main
RubyVM to signal the timer thread shutdown.

To effectively close pipes, we implement userspace locks via
atomics to force the pipe closing thread to wait on any signal
handlers which may be waking up.

While we're at it, improve robustness during resource exhaustion and
allow it to limp along non-fatally if restarting a timer thread
fails.

Note: this change is tested with VM_CHECK_MODE 1 in vm_core.h
---
 eval.c           |   2 +-
 process.c        |  48 ++++-------------
 thread.c         |   4 +-
 thread_pthread.c | 158 +++++++++++++++++++++++++++++++------------------------
 thread_win32.c   |   8 +--
 vm_core.h        |   2 +-
 6 files changed, 105 insertions(+), 117 deletions(-)

diff --git a/eval.c b/eval.c
index af88e4b..f598525 100644
--- a/eval.c
+++ b/eval.c
@@ -223,7 +223,7 @@ ruby_cleanup(volatile int ex)
     /* unlock again if finalizer took mutexes. */
     rb_threadptr_unlock_all_locking_mutexes(GET_THREAD());
     TH_POP_TAG();
-    rb_thread_stop_timer_thread(1);
+    rb_thread_stop_timer_thread();
     ruby_vm_destruct(GET_VM());
     if (state) ruby_default_signal(state);
 
diff --git a/process.c b/process.c
index cdc9692..206a445 100644
--- a/process.c
+++ b/process.c
@@ -297,24 +297,14 @@ extern ID ruby_static_id_status;
 static inline int
 close_unless_reserved(int fd)
 {
-    /* Do nothing to the reserved fd because it should be closed in exec(2)
-       due to the O_CLOEXEC or FD_CLOEXEC flag. */
+    /* We should not have reserved FDs at this point */
     if (rb_reserved_fd_p(fd)) { /* async-signal-safe */
+        rb_async_bug_errno("BUG timer thread still running", 0 /* EDOOFUS */);
         return 0;
     }
     return close(fd); /* async-signal-safe */
 }
 
-static inline int
-dup2_with_divert(int oldfd, int newfd)
-{
-    if (rb_divert_reserved_fd(newfd) == -1) { /* async-signal-safe if no error occurred */
-        return -1;
-    } else {
-        return dup2(oldfd, newfd); /* async-signal-safe */
-    }
-}
-
 /*#define DEBUG_REDIRECT*/
 #if defined(DEBUG_REDIRECT)
 
@@ -354,7 +344,7 @@ static int
 redirect_dup2(int oldfd, int newfd)
 {
     int ret;
-    ret = dup2_with_divert(oldfd, newfd);
+    ret = dup2(oldfd, newfd);
     ttyprintf("dup2(%d, %d) => %d\n", oldfd, newfd, ret);
     return ret;
 }
@@ -388,7 +378,7 @@ parent_redirect_close(int fd)
 
 #else
 #define redirect_dup(oldfd) dup(oldfd)
-#define redirect_dup2(oldfd, newfd) dup2_with_divert((oldfd), (newfd))
+#define redirect_dup2(oldfd, newfd) dup2((oldfd), (newfd))
 #define redirect_close(fd) close_unless_reserved(fd)
 #define parent_redirect_open(pathname, flags, perm) rb_cloexec_open((pathname), (flags), (perm))
 #define parent_redirect_close(fd) close_unless_reserved(fd)
@@ -1151,8 +1141,10 @@ before_exec_non_async_signal_safe(void)
      * internal threads temporary. [ruby-core:10583]
      * This is also true on Haiku. It returns Errno::EPERM against exec()
      * in multiple threads.
+     *
+     * Nowadays, we always stop the timer thread completely to allow redirects.
      */
-    rb_thread_stop_timer_thread(0);
+    rb_thread_stop_timer_thread();
 }
 
 static void
@@ -2472,10 +2464,6 @@ rb_execarg_parent_end(VALUE execarg_obj)
     RB_GC_GUARD(execarg_obj);
 }
 
-#if defined(__APPLE__) || defined(__HAIKU__)
-static int rb_exec_without_timer_thread(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen);
-#endif
-
 /*
  *  call-seq:
  *     exec([env,] command... [,options])
@@ -2559,16 +2547,14 @@ rb_f_exec(int argc, const VALUE *argv)
 
     execarg_obj = rb_execarg_new(argc, argv, TRUE);
     eargp = rb_execarg_get(execarg_obj);
+    before_exec(); /* stop timer thread before redirects */
     rb_execarg_parent_start(execarg_obj);
     fail_str = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
 
-#if defined(__APPLE__) || defined(__HAIKU__)
-    rb_exec_without_timer_thread(eargp, errmsg, sizeof(errmsg));
-#else
-    before_exec_async_signal_safe(); /* async-signal-safe */
     rb_exec_async_signal_safe(eargp, errmsg, sizeof(errmsg));
-    preserving_errno(after_exec_async_signal_safe()); /* async-signal-safe */
-#endif
+
+    preserving_errno(after_exec()); /* restart timer thread */
+
     RB_GC_GUARD(execarg_obj);
     if (errmsg[0])
         rb_sys_fail(errmsg);
@@ -3076,18 +3062,6 @@ failure:
     return -1;
 }
 
-#if defined(__APPLE__) || defined(__HAIKU__)
-static int
-rb_exec_without_timer_thread(const struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
-{
-    int ret;
-    before_exec();
-    ret = rb_exec_async_signal_safe(eargp, errmsg, errmsg_buflen); /* hopefully async-signal-safe */
-    preserving_errno(after_exec()); /* not async-signal-safe because it calls rb_thread_start_timer_thread.  */
-    return ret;
-}
-#endif
-
 #ifdef HAVE_WORKING_FORK
 /* This function should be async-signal-safe.  Hopefully it is. */
 static int
diff --git a/thread.c b/thread.c
index dfd2b21..581071e 100644
--- a/thread.c
+++ b/thread.c
@@ -3863,9 +3863,9 @@ timer_thread_function(void *arg)
 }
 
 void
-rb_thread_stop_timer_thread(int close_anyway)
+rb_thread_stop_timer_thread(void)
 {
-    if (TIMER_THREAD_CREATED_P() && native_stop_timer_thread(close_anyway)) {
+    if (TIMER_THREAD_CREATED_P() && native_stop_timer_thread()) {
 	native_reset_timer_thread();
     }
 }
diff --git a/thread_pthread.c b/thread_pthread.c
index 4eca11d..3742741 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -1232,9 +1232,16 @@ static int check_signal_thread_list(void) { return 0; }
 
 #if USE_SLEEPY_TIMER_THREAD
 static struct {
+    /*
+     * Read end of each pipe is closed inside timer thread for shutdown
+     * Write ends are closed by a normal Ruby thread during shutdown
+     */
     int normal[2];
     int low[2];
-    rb_pid_t owner_process;
+
+    /* volatile for signal handler use: */
+    volatile rb_pid_t owner_process;
+    rb_atomic_t writing;
 } timer_thread_pipe = {
     {-1, -1},
     {-1, -1}, /* low priority */
@@ -1242,12 +1249,13 @@ static struct {
 
 /* only use signal-safe system calls here */
 static void
-rb_thread_wakeup_timer_thread_fd(int fd)
+rb_thread_wakeup_timer_thread_fd(volatile int *fdp)
 {
     ssize_t result;
+    int fd = *fdp;
 
     /* already opened */
-    if (timer_thread_pipe.owner_process == getpid()) {
+    if (fd >= 0 && timer_thread_pipe.owner_process == getpid()) {
 	const char *buff = "!";
       retry:
 	if ((result = write(fd, buff, 1)) <= 0) {
@@ -1273,13 +1281,18 @@ rb_thread_wakeup_timer_thread_fd(int fd)
 void
 rb_thread_wakeup_timer_thread(void)
 {
-    rb_thread_wakeup_timer_thread_fd(timer_thread_pipe.normal[1]);
+    /* must be safe inside sighandler, so no mutex */
+    ATOMIC_INC(timer_thread_pipe.writing);
+    rb_thread_wakeup_timer_thread_fd(&timer_thread_pipe.normal[1]);
+    ATOMIC_DEC(timer_thread_pipe.writing);
 }
 
 static void
 rb_thread_wakeup_timer_thread_low(void)
 {
-    rb_thread_wakeup_timer_thread_fd(timer_thread_pipe.low[1]);
+    ATOMIC_INC(timer_thread_pipe.writing);
+    rb_thread_wakeup_timer_thread_fd(&timer_thread_pipe.low[1]);
+    ATOMIC_DEC(timer_thread_pipe.writing);
 }
 
 /* VM-dependent API is not available for this function */
@@ -1313,16 +1326,16 @@ consume_communication_pipe(int fd)
     }
 }
 
+#define CLOSE_INVALIDATE(expr) close_invalidate(&expr,#expr)
 static void
-close_communication_pipe(int pipes[2])
+close_invalidate(volatile int *fdp, const char *msg)
 {
-    if (close(pipes[0]) < 0) {
-	rb_bug_errno("native_stop_timer_thread - close(ttp[0])", errno);
-    }
-    if (close(pipes[1]) < 0) {
-	rb_bug_errno("native_stop_timer_thread - close(ttp[1])", errno);
+    int fd = *fdp;
+
+    *fdp = -1;
+    if (close(fd) < 0) {
+	rb_async_bug_errno(msg, errno);
     }
-    pipes[0] = pipes[1] = -1;
 }
 
 static void
@@ -1340,39 +1353,47 @@ set_nonblock(int fd)
 	rb_sys_fail(0);
 }
 
-static void
+static int
 setup_communication_pipe_internal(int pipes[2])
 {
     int err;
 
-    if (pipes[0] != -1) {
-	/* close pipe of parent process */
-	close_communication_pipe(pipes);
-    }
-
     err = rb_cloexec_pipe(pipes);
     if (err != 0) {
-	rb_bug_errno("setup_communication_pipe: Failed to create communication pipe for timer thread", errno);
+	rb_warn("Failed to create communication pipe for timer thread: %s",
+	        strerror(errno));
+	return -1;
     }
     rb_update_max_fd(pipes[0]);
     rb_update_max_fd(pipes[1]);
     set_nonblock(pipes[0]);
     set_nonblock(pipes[1]);
+    return 0;
 }
 
 /* communication pipe with timer thread and signal handler */
-static void
+static int
 setup_communication_pipe(void)
 {
-    if (timer_thread_pipe.owner_process == getpid()) {
-	/* already set up. */
-	return;
+    VM_ASSERT(timer_thread_pipe.owner_process == 0);
+    VM_ASSERT(timer_thread_pipe.normal[0] == -1);
+    VM_ASSERT(timer_thread_pipe.normal[1] == -1);
+    VM_ASSERT(timer_thread_pipe.low[0] == -1);
+    VM_ASSERT(timer_thread_pipe.low[1] == -1);
+
+    if (setup_communication_pipe_internal(timer_thread_pipe.normal) < 0) {
+	return errno;
+    }
+    if (setup_communication_pipe_internal(timer_thread_pipe.low) < 0) {
+	int e = errno;
+	CLOSE_INVALIDATE(timer_thread_pipe.normal[0]);
+	CLOSE_INVALIDATE(timer_thread_pipe.normal[1]);
+	return e;
     }
-    setup_communication_pipe_internal(timer_thread_pipe.normal);
-    setup_communication_pipe_internal(timer_thread_pipe.low);
 
     /* validate pipe on this process */
     timer_thread_pipe.owner_process = getpid();
+    return 0;
 }
 
 /**
@@ -1509,7 +1530,10 @@ thread_timer(void *p)
         /* wait */
 	timer_thread_sleep(gvl);
     }
-#if !USE_SLEEPY_TIMER_THREAD
+#if USE_SLEEPY_TIMER_THREAD
+    CLOSE_INVALIDATE(timer_thread_pipe.normal[0]);
+    CLOSE_INVALIDATE(timer_thread_pipe.low[0]);
+#else
     native_mutex_unlock(&timer_thread_lock);
     native_cond_destroy(&timer_thread_cond);
     native_mutex_destroy(&timer_thread_lock);
@@ -1529,8 +1553,9 @@ rb_thread_create_timer_thread(void)
 
 	err = pthread_attr_init(&attr);
 	if (err != 0) {
-	    fprintf(stderr, "[FATAL] Failed to initialize pthread attr: %s\n", strerror(err));
-	    exit(EXIT_FAILURE);
+	    rb_warn("pthread_attr_init failed for timer: %s, scheduling broken",
+		    strerror(err));
+	    return;
         }
 # ifdef PTHREAD_STACK_MIN
 	{
@@ -1548,7 +1573,12 @@ rb_thread_create_timer_thread(void)
 #endif
 
 #if USE_SLEEPY_TIMER_THREAD
-	setup_communication_pipe();
+	err = setup_communication_pipe();
+	if (err != 0) {
+	    rb_warn("pipe creation failed for timer: %s, scheduling broken",
+		    strerror(err));
+	    return;
+	}
 #endif /* USE_SLEEPY_TIMER_THREAD */
 
 	/* create timer thread */
@@ -1561,8 +1591,13 @@ rb_thread_create_timer_thread(void)
 	err = pthread_create(&timer_thread.id, NULL, thread_timer, &GET_VM()->gvl);
 #endif
 	if (err != 0) {
-	    fprintf(stderr, "[FATAL] Failed to create timer thread: %s\n", strerror(err));
-	    exit(EXIT_FAILURE);
+	    rb_warn("pthread_create failed for timer: %s, scheduling broken",
+		    strerror(err));
+	    CLOSE_INVALIDATE(timer_thread_pipe.normal[0]);
+	    CLOSE_INVALIDATE(timer_thread_pipe.normal[1]);
+	    CLOSE_INVALIDATE(timer_thread_pipe.low[0]);
+	    CLOSE_INVALIDATE(timer_thread_pipe.low[1]);
+	    return;
 	}
 	timer_thread.created = 1;
 #ifdef HAVE_PTHREAD_ATTR_INIT
@@ -1572,30 +1607,38 @@ rb_thread_create_timer_thread(void)
 }
 
 static int
-native_stop_timer_thread(int close_anyway)
+native_stop_timer_thread(void)
 {
     int stopped;
     stopped = --system_working <= 0;
 
     if (TT_DEBUG) fprintf(stderr, "stop timer thread\n");
     if (stopped) {
-	/* join */
-	rb_thread_wakeup_timer_thread();
+	/* prevent wakeups from signal handler ASAP */
+	timer_thread_pipe.owner_process = 0;
+
+	/*
+	 * however, the above was not enough: the FD may already be
+	 * captured and in the middle of a write while we are running,
+	 * so wait for that to finish:
+	 */
+	while (ATOMIC_CAS(timer_thread_pipe.writing, 0, 0)) {
+	    native_thread_yield();
+	}
+
+	/* stop writing ends of pipes so timer thread notices EOF */
+	CLOSE_INVALIDATE(timer_thread_pipe.normal[1]);
+	CLOSE_INVALIDATE(timer_thread_pipe.low[1]);
+
+	/* timer thread will stop looping when system_working <= 0: */
 	native_thread_join(timer_thread.id);
+
+	/* timer thread will close the read end on exit: */
+	VM_ASSERT(timer_thread_pipe.normal[0] == -1);
+	VM_ASSERT(timer_thread_pipe.low[0] == -1);
+
 	if (TT_DEBUG) fprintf(stderr, "joined timer thread\n");
 	timer_thread.created = 0;
-
-	/* close communication pipe */
-	if (close_anyway) {
-	    /* TODO: Uninstall all signal handlers or mask all signals.
-	     *       This pass is cleaning phase (terminate ruby process).
-	     *       To avoid such race, we skip to close communication
-	     *       pipe.  OS will close it at process termination.
-	     *       It may not good practice, but pragmatic.
-	     *       We remain it is TODO.
-	     */
-	    /* close_communication_pipe(); */
-	}
     }
     return stopped;
 }
@@ -1669,29 +1712,6 @@ rb_reserved_fd_p(int fd)
 #endif
 }
 
-int
-rb_divert_reserved_fd(int fd)
-{
-#if USE_SLEEPY_TIMER_THREAD
-    int *ptr;
-    int newfd;
-
-    if ((fd == *(ptr = &(timer_thread_pipe.normal[0])) ||
-         fd == *(ptr = &(timer_thread_pipe.normal[1])) ||
-         fd == *(ptr = &(timer_thread_pipe.low[0])) ||
-         fd == *(ptr = &(timer_thread_pipe.low[1]))) &&
-        timer_thread_pipe.owner_process == getpid()) { /* async-signal-safe */
-        newfd = rb_cloexec_dup(fd); /* async-signal-safe if no error */
-        if (newfd == -1) return -1;
-        rb_update_max_fd(newfd); /* async-signal-safe if no error */
-        /* set_nonblock(newfd); */ /* async-signal-safe if no error */
-        *ptr = newfd;
-        rb_thread_wakeup_timer_thread_low(); /* async-signal-safe? */
-    }
-#endif
-    return 0;
-}
-
 rb_nativethread_id_t
 rb_nativethread_self(void)
 {
diff --git a/thread_win32.c b/thread_win32.c
index 2dd377d..2dfbf06 100644
--- a/thread_win32.c
+++ b/thread_win32.c
@@ -730,7 +730,7 @@ rb_thread_create_timer_thread(void)
 }
 
 static int
-native_stop_timer_thread(int close_anyway)
+native_stop_timer_thread(void)
 {
     int stopped = --system_working <= 0;
     if (stopped) {
@@ -788,12 +788,6 @@ rb_reserved_fd_p(int fd)
     return 0;
 }
 
-int
-rb_divert_reserved_fd(int fd)
-{
-    return 0;
-}
-
 rb_nativethread_id_t
 rb_nativethread_self(void)
 {
diff --git a/vm_core.h b/vm_core.h
index a032daa..cad0e09 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -979,7 +979,7 @@ VALUE rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc,
 		 const VALUE *argv, const rb_callable_method_entry_t *me);
 
 void rb_thread_start_timer_thread(void);
-void rb_thread_stop_timer_thread(int);
+void rb_thread_stop_timer_thread(void);
 void rb_thread_reset_timer_thread(void);
 void rb_thread_wakeup_timer_thread(void);
 
-- 
EW


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/5] digest: remove needless volatile
  2015-08-12 19:23 [PATCH 1/5] net/http: retryable exception is configurable Eric Wong
  2015-08-12 19:23 ` [PATCH 2/5] thread_pthread: eliminate malloc from signal thread list Eric Wong
  2015-08-12 19:23 ` [PATCH 3/5] improve handling of timer thread shutdown Eric Wong
@ 2015-08-12 19:23 ` Eric Wong
  2015-08-12 19:23 ` [PATCH 5/5] remove needless volatile from ALLOCV_N + friends Eric Wong
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Wong @ 2015-08-12 19:23 UTC (permalink / raw)
  To: spew

---
 ext/digest/digest.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index a02eb12..7be7bcc 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -458,7 +458,7 @@ static VALUE
 rb_digest_class_s_digest(int argc, VALUE *argv, VALUE klass)
 {
     VALUE str;
-    volatile VALUE obj;
+    VALUE obj;
 
     if (argc < 1) {
         rb_raise(rb_eArgError, "no data given");
-- 
EW


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 5/5] remove needless volatile from ALLOCV_N + friends
  2015-08-12 19:23 [PATCH 1/5] net/http: retryable exception is configurable Eric Wong
                   ` (2 preceding siblings ...)
  2015-08-12 19:23 ` [PATCH 4/5] digest: remove needless volatile Eric Wong
@ 2015-08-12 19:23 ` Eric Wong
  3 siblings, 0 replies; 5+ messages in thread
From: Eric Wong @ 2015-08-12 19:23 UTC (permalink / raw)
  To: spew

Stop allowing it
---
 array.c             | 8 ++++----
 gc.c                | 4 ++--
 include/ruby/ruby.h | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/array.c b/array.c
index 27b6325..d08e2f5 100644
--- a/array.c
+++ b/array.c
@@ -4982,7 +4982,7 @@ rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
 	}
     }
     else {             /* this is the general case */
-	volatile VALUE t0;
+	VALUE t0;
 	long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
 	char *used = (char*)(p + r);
 	VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
@@ -5073,7 +5073,7 @@ rb_ary_combination(VALUE ary, VALUE num)
     }
     else {
 	VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
-	volatile VALUE t0;
+	VALUE t0;
 	long *stack = ALLOCV_N(long, t0, n+1);
 
 	RBASIC_CLEAR_CLASS(ary0);
@@ -5178,7 +5178,7 @@ rb_ary_repeated_permutation(VALUE ary, VALUE num)
 	}
     }
     else {             /* this is the general case */
-	volatile VALUE t0;
+	VALUE t0;
 	long *p = ALLOCV_N(long, t0, r * sizeof(long));
 	VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
 	RBASIC_CLEAR_CLASS(ary0);
@@ -5274,7 +5274,7 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
 	/* yield nothing */
     }
     else {
-	volatile VALUE t0;
+	VALUE t0;
 	long *p = ALLOCV_N(long, t0, n);
 	VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
 	RBASIC_CLEAR_CLASS(ary0);
diff --git a/gc.c b/gc.c
index a3af6fe..44080ec 100644
--- a/gc.c
+++ b/gc.c
@@ -7767,7 +7767,7 @@ ruby_mimfree(void *ptr)
 }
 
 void *
-rb_alloc_tmp_buffer(volatile VALUE *store, long len)
+rb_alloc_tmp_buffer(VALUE *store, long len)
 {
     NODE *s;
     long cnt;
@@ -7786,7 +7786,7 @@ rb_alloc_tmp_buffer(volatile VALUE *store, long len)
 }
 
 void
-rb_free_tmp_buffer(volatile VALUE *store)
+rb_free_tmp_buffer(VALUE *store)
 {
     VALUE s = ATOMIC_VALUE_EXCHANGE(*store, 0);
     if (s) {
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 01b3c2e..d853fca 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1429,8 +1429,8 @@ rb_num2char_inline(VALUE x)
 
 #define ALLOCA_N(type,n) ((type*)alloca(sizeof(type)*(n)))
 
-void *rb_alloc_tmp_buffer(volatile VALUE *store, long len) RUBY_ATTR_ALLOC_SIZE((2));
-void rb_free_tmp_buffer(volatile VALUE *store);
+void *rb_alloc_tmp_buffer(VALUE *store, long len) RUBY_ATTR_ALLOC_SIZE((2));
+void rb_free_tmp_buffer(VALUE *store);
 /* allocates _n_ bytes temporary buffer and stores VALUE including it
  * in _v_.  _n_ may be evaluated twice. */
 #ifdef C_ALLOCA
-- 
EW


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-08-12 19:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-12 19:23 [PATCH 1/5] net/http: retryable exception is configurable Eric Wong
2015-08-12 19:23 ` [PATCH 2/5] thread_pthread: eliminate malloc from signal thread list Eric Wong
2015-08-12 19:23 ` [PATCH 3/5] improve handling of timer thread shutdown Eric Wong
2015-08-12 19:23 ` [PATCH 4/5] digest: remove needless volatile Eric Wong
2015-08-12 19:23 ` [PATCH 5/5] remove needless volatile from ALLOCV_N + friends Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).