summaryrefslogtreecommitdiffhomepage
path: root/src/io.c
diff options
context:
space:
mode:
authorTomoyuki Sahara <[email protected]>2015-08-26 17:37:21 +0900
committerTomoyuki Sahara <[email protected]>2015-08-26 17:37:21 +0900
commit6c4d39412f693301eca34daf7a413248839be404 (patch)
tree4e7c0a5d496ab097638055c1a724cc61a32e9688 /src/io.c
parent042e4a43133f0476db107a3c9f5bf35bab681014 (diff)
parente61c46972482ca2b4e9b338f9ccfa4ee13efa62d (diff)
downloadmruby-6c4d39412f693301eca34daf7a413248839be404.tar.gz
mruby-6c4d39412f693301eca34daf7a413248839be404.zip
Merge pull request #30 from ksss/cloexec
Opened fd should be set FD_CLOEXEC by default
Diffstat (limited to 'src/io.c')
-rw-r--r--src/io.c96
1 files changed, 73 insertions, 23 deletions
diff --git a/src/io.c b/src/io.c
index ad3e3c3b7..1d2f98f3c 100644
--- a/src/io.c
+++ b/src/io.c
@@ -125,6 +125,30 @@ mrb_io_flags_to_modenum(mrb_state *mrb, int flags)
return modenum;
}
+void
+mrb_fd_cloexec(mrb_state *mrb, int fd)
+{
+ int flags, flags2;
+
+#if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
+ flags = fcntl(fd, F_GETFD);
+ if (flags == -1) {
+ mrb_sys_fail(mrb, "fcntl");
+ }
+ if (fd <= 2) {
+ flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
+ }
+ else {
+ flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
+ }
+ if (flags != flags2) {
+ if (fcntl(fd, F_SETFD, flags2) == -1) {
+ mrb_sys_fail(mrb, "fcntl");
+ }
+ }
+#endif
+}
+
#ifndef _WIN32
static int
mrb_proc_exec(const char *pname)
@@ -199,13 +223,22 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
doexec = (strcmp("-", pname) != 0);
- if ((flags & FMODE_READABLE) && pipe(pr) == -1) {
- mrb_sys_fail(mrb, "pipe");
+ if (flags & FMODE_READABLE) {
+ if (pipe(pr) == -1) {
+ mrb_sys_fail(mrb, "pipe");
+ }
+ mrb_fd_cloexec(mrb, pr[0]);
+ mrb_fd_cloexec(mrb, pr[1]);
}
- if ((flags & FMODE_WRITABLE) && pipe(pw) == -1) {
- if (pr[0] != -1) close(pr[0]);
- if (pr[1] != -1) close(pr[1]);
- mrb_sys_fail(mrb, "pipe");
+
+ if (flags & FMODE_WRITABLE) {
+ if (pipe(pw) == -1) {
+ if (pr[0] != -1) close(pr[0]);
+ if (pr[1] != -1) close(pr[1]);
+ mrb_sys_fail(mrb, "pipe");
+ }
+ mrb_fd_cloexec(mrb, pw[0]);
+ mrb_fd_cloexec(mrb, pw[1]);
}
if (!doexec) {
@@ -389,6 +422,38 @@ mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
return mrb_fixnum_value(0);
}
+int
+mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
+{
+ int fd, retry = FALSE;
+
+#ifdef O_CLOEXEC
+ /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
+ flags |= O_CLOEXEC;
+#elif defined O_NOINHERIT
+ flags |= O_NOINHERIT;
+#endif
+reopen:
+ fd = open(pathname, flags, mode);
+ if (fd == -1) {
+ if (!retry) {
+ switch (errno) {
+ case ENFILE:
+ case EMFILE:
+ mrb_garbage_collect(mrb);
+ retry = TRUE;
+ goto reopen;
+ }
+ }
+ mrb_sys_fail(mrb, "open");
+ }
+
+ if (fd <= 2) {
+ mrb_fd_cloexec(mrb, fd);
+ }
+ return fd;
+}
+
mrb_value
mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
{
@@ -396,7 +461,7 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
mrb_value mode = mrb_nil_value();
mrb_int fd, flags, perm = -1;
const char *pat;
- int modenum, retry = FALSE;
+ int modenum;
mrb_get_args(mrb, "S|Si", &path, &mode, &perm);
if (mrb_nil_p(mode)) {
@@ -409,22 +474,7 @@ mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
pat = mrb_string_value_cstr(mrb, &path);
flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode));
modenum = mrb_io_flags_to_modenum(mrb, flags);
-
- reopen:
- fd = open(pat, modenum, perm);
- if (fd == -1) {
- if (!retry) {
- switch (errno) {
- case ENFILE:
- case EMFILE:
- mrb_garbage_collect(mrb);
- retry = TRUE;
- goto reopen;
- }
- }
- mrb_sys_fail(mrb, pat);
- }
-
+ fd = mrb_cloexec_open(mrb, pat, modenum, perm);
return mrb_fixnum_value(fd);
}