diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-08-19 08:01:26 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-08-19 08:01:26 +0000 |
commit | 7f9f6c3122ecf320af00e3602619c404d9772046 (patch) | |
tree | 41585b87746dd7bbc6dc6f3f16a8f788b050e197 /process.c | |
parent | 5a096eddb34fcff83c5662925e5440c410409af0 (diff) | |
download | ruby-7f9f6c3122ecf320af00e3602619c404d9772046.tar.gz |
process.c: retry fork if ENOMEM
* process.c (retry_fork): retry with GC if ENOMEM occurred, to free
swap/kernel space.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42618 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'process.c')
-rw-r--r-- | process.c | 20 |
1 files changed, 13 insertions, 7 deletions
@@ -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; } } |