diff --git a/ChangeLog b/ChangeLog index 0eff2ba199..71412156d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Mon Aug 19 17:00:53 2013 Nobuyoshi Nakada + + * process.c (retry_fork): retry with GC if ENOMEM occurred, to free + swap/kernel space. + Mon Aug 19 13:28:47 2013 NAKAMURA Usaku * include/ruby/win32.h (CLOCK_MONOTONIC): typo. diff --git a/process.c b/process.c index 35b418f06b..187bac2b1a 100644 --- a/process.c +++ b/process.c @@ -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; } }