diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | process.c | 20 |
2 files changed, 18 insertions, 7 deletions
@@ -1,3 +1,8 @@ +Mon Aug 19 17:00:53 2013 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * process.c (retry_fork): retry with GC if ENOMEM occurred, to free + swap/kernel space. + Mon Aug 19 13:28:47 2013 NAKAMURA Usaku <usa@ruby-lang.org> * include/ruby/win32.h (CLOCK_MONOTONIC): typo. @@ -3246,6 +3246,7 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe) { rb_pid_t pid; int state = 0; + int try_gc = 1; #define prefork() ( \ rb_io_flush(rb_stdout), \ @@ -3265,6 +3266,12 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe) return pid; /* fork failed */ switch (errno) { + case ENOMEM: + if (try_gc-- > 0 && !rb_during_gc()) { + rb_gc(); + continue; + } + break; case EAGAIN: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: @@ -3278,14 +3285,13 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe) if (status) *status = state; if (!state) continue; } - /* fall through */ - default: - if (ep) { - preserving_errno((close(ep[0]), close(ep[1]))); - } - if (state && !status) rb_jump_tag(state); - return -1; + break; + } + if (ep) { + preserving_errno((close(ep[0]), close(ep[1]))); } + if (state && !status) rb_jump_tag(state); + return -1; } } |