summaryrefslogtreecommitdiff
path: root/process.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-02 11:47:35 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-02 11:47:35 +0000
commit557802a1daec5fd3d33f42ddb974b0739a081ecb (patch)
tree88034ca99f6f4a2be691a2c74504c100e3a4dc10 /process.c
parentbd1f4738a443a196203d51ee95f137fe7e688311 (diff)
* process.c (handle_fork_error): Extracted from retry_fork.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47351 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'process.c')
-rw-r--r--process.c71
1 files changed, 39 insertions, 32 deletions
diff --git a/process.c b/process.c
index bcccddcdcd..f2bf7c13af 100644
--- a/process.c
+++ b/process.c
@@ -3173,6 +3173,43 @@ chfunc_protect(VALUE arg)
#define O_BINARY 0
#endif
+static int
+handle_fork_error(int *status, int *ep, int *state_p, int *try_gc_p)
+{
+ switch (errno) {
+ case ENOMEM:
+ if ((*try_gc_p)-- > 0 && !rb_during_gc()) {
+ rb_gc();
+ return 0;
+ }
+ break;
+ case EAGAIN:
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ if (!status && !ep) {
+ rb_thread_sleep(1);
+ return 0;
+ }
+ else {
+ rb_protect((VALUE (*)())rb_thread_sleep, 1, state_p);
+ if (status) *status = *state_p;
+ if (!*state_p) return 0;
+ }
+ break;
+ }
+ if (ep) {
+ preserving_errno((close(ep[0]), close(ep[1])));
+ }
+ if (*state_p && !status) rb_jump_tag(*state_p);
+ return -1;
+}
+
+#define prefork() ( \
+ rb_io_flush(rb_stdout), \
+ rb_io_flush(rb_stderr) \
+ )
+
/*
* Forks child process, and returns the process ID in the parent
* process.
@@ -3206,11 +3243,6 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe)
int state = 0;
int try_gc = 1;
-#define prefork() ( \
- rb_io_flush(rb_stdout), \
- rb_io_flush(rb_stderr) \
- )
-
while (1) {
prefork();
if (!chfunc_is_async_signal_safe)
@@ -3223,33 +3255,8 @@ retry_fork(int *status, int *ep, int chfunc_is_async_signal_safe)
if (0 < pid) /* fork succeed, parent process */
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:
-#endif
- if (!status && !ep) {
- rb_thread_sleep(1);
- continue;
- }
- else {
- rb_protect((VALUE (*)())rb_thread_sleep, 1, &state);
- if (status) *status = state;
- if (!state) continue;
- }
- break;
- }
- if (ep) {
- preserving_errno((close(ep[0]), close(ep[1])));
- }
- if (state && !status) rb_jump_tag(state);
- return -1;
+ if (handle_fork_error(status, ep, &state, &try_gc))
+ return -1;
}
}