summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-08-19 08:01:26 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-08-19 08:01:26 +0000
commit7f9f6c3122ecf320af00e3602619c404d9772046 (patch)
tree41585b87746dd7bbc6dc6f3f16a8f788b050e197
parent5a096eddb34fcff83c5662925e5440c410409af0 (diff)
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
-rw-r--r--ChangeLog5
-rw-r--r--process.c20
2 files changed, 18 insertions, 7 deletions
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 <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.
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;
}
}