aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2023-08-16 20:47:28 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2023-08-16 22:53:00 +0900
commit7d3634a121736eea1a43a332b9abd0540d3a6300 (patch)
tree4ca6d2d68a670b5405bb23772356f512d9df3abb /io.c
parentf0edcd8283e1aeda9ff2d04926ec8041b421f890 (diff)
downloadruby-7d3634a121736eea1a43a332b9abd0540d3a6300.tar.gz
Extract GC for fd parts as `TRY_WITH_GC `
Diffstat (limited to 'io.c')
-rw-r--r--io.c57
1 files changed, 22 insertions, 35 deletions
diff --git a/io.c b/io.c
index 90b6cc1db0..6e27ed6273 100644
--- a/io.c
+++ b/io.c
@@ -1063,20 +1063,24 @@ rb_gc_for_fd(int err)
return 0;
}
+/* try `expr` upto twice while it returns false and `errno`
+ * is to GC. Each `errno`s are available as `first_errno` and
+ * `retried_errno` respectively */
+#define TRY_WITH_GC(expr) \
+ for (int first_errno, retried_errno = 0, retried = 0; \
+ (!retried && \
+ !(expr) && \
+ (!rb_gc_for_fd(first_errno = errno) || !(expr)) && \
+ (retried_errno = errno, 1)); \
+ (void)retried_errno, retried = 1)
+
static int
ruby_dup(int orig)
{
- int fd;
+ int fd = -1;
- fd = rb_cloexec_dup(orig);
- if (fd < 0) {
- int e = errno;
- if (rb_gc_for_fd(e)) {
- fd = rb_cloexec_dup(orig);
- }
- if (fd < 0) {
- rb_syserr_fail(e, 0);
- }
+ TRY_WITH_GC((fd = rb_cloexec_dup(orig)) >= 0) {
+ rb_syserr_fail(first_errno, 0);
}
rb_update_max_fd(fd);
return fd;
@@ -6945,7 +6949,7 @@ rb_sysopen_internal(struct sysopen_struct *data)
static int
rb_sysopen(VALUE fname, int oflags, mode_t perm)
{
- int fd;
+ int fd = -1;
struct sysopen_struct data;
data.fname = rb_str_encode_ospath(fname);
@@ -6953,15 +6957,8 @@ rb_sysopen(VALUE fname, int oflags, mode_t perm)
data.oflags = oflags;
data.perm = perm;
- fd = rb_sysopen_internal(&data);
- if (fd < 0) {
- int e = errno;
- if (rb_gc_for_fd(e)) {
- fd = rb_sysopen_internal(&data);
- }
- if (fd < 0) {
- rb_syserr_fail_path(e, fname);
- }
+ TRY_WITH_GC((fd = rb_sysopen_internal(&data)) >= 0) {
+ rb_syserr_fail_path(first_errno, fname);
}
return fd;
}
@@ -6988,15 +6985,10 @@ fdopen_internal(int fd, const char *modestr)
FILE *
rb_fdopen(int fd, const char *modestr)
{
- FILE *file = fdopen_internal(fd, modestr);
- if (!file) {
- int e = errno;
- if (rb_gc_for_fd(e)) {
- file = fdopen_internal(fd, modestr);
- }
- if (!file) {
- rb_syserr_fail(e, 0);
- }
+ FILE *file = 0;
+
+ TRY_WITH_GC((file = fdopen_internal(fd, modestr)) != 0) {
+ rb_syserr_fail(first_errno, 0);
}
/* xxx: should be _IONBF? A buffer in FILE may have trouble. */
@@ -7287,12 +7279,7 @@ int
rb_pipe(int *pipes)
{
int ret;
- ret = rb_cloexec_pipe(pipes);
- if (ret < 0) {
- if (rb_gc_for_fd(errno)) {
- ret = rb_cloexec_pipe(pipes);
- }
- }
+ TRY_WITH_GC((ret = rb_cloexec_pipe(pipes)) >= 0);
if (ret == 0) {
rb_update_max_fd(pipes[0]);
rb_update_max_fd(pipes[1]);