Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make File#chmod and File#chown unblocking #10166

Merged
merged 2 commits into from Mar 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
99 changes: 95 additions & 4 deletions file.c
Expand Up @@ -2547,6 +2547,29 @@ file_size(VALUE self)
return OFFT2NUM(rb_file_size(self));
}

struct nogvl_chmod_data {
const char *path;
mode_t mode;
};

static void *
nogvl_chmod(void *ptr)
{
struct nogvl_chmod_data *data = ptr;
int ret = chmod(data->path, data->mode);
return (void *)(VALUE)ret;
}

static int
rb_chmod(const char *path, mode_t mode)
{
struct nogvl_chmod_data data = {
.path = path,
.mode = mode,
};
return IO_WITHOUT_GVL_INT(nogvl_chmod, &data);
}

static int
chmod_internal(const char *path, void *mode)
{
Expand Down Expand Up @@ -2577,6 +2600,29 @@ rb_file_s_chmod(int argc, VALUE *argv, VALUE _)
return apply2files(chmod_internal, argc, argv, &mode);
}

#ifdef HAVE_FCHMOD
struct nogvl_fchmod_data {
int fd;
mode_t mode;
};

static VALUE
io_blocking_fchmod(void *ptr)
{
struct nogvl_fchmod_data *data = ptr;
int ret = fchmod(data->fd, data->mode);
return (VALUE)ret;
}

static int
rb_fchmod(int fd, mode_t mode)
{
(void)rb_chmod; /* suppress unused-function warning when HAVE_FCHMOD */
struct nogvl_fchmod_data data = {.fd = fd, .mode = mode};
return (int)rb_thread_io_blocking_region(io_blocking_fchmod, &data, fd);
}
#endif

/*
* call-seq:
* file.chmod(mode_int) -> 0
Expand All @@ -2603,7 +2649,7 @@ rb_file_chmod(VALUE obj, VALUE vmode)

GetOpenFile(obj, fptr);
#ifdef HAVE_FCHMOD
if (fchmod(fptr->fd, mode) == -1) {
if (rb_fchmod(fptr->fd, mode) == -1) {
if (HAVE_FCHMOD || errno != ENOSYS)
rb_sys_fail_path(fptr->pathv);
}
Expand All @@ -2614,7 +2660,7 @@ rb_file_chmod(VALUE obj, VALUE vmode)
#if !defined HAVE_FCHMOD || !HAVE_FCHMOD
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (chmod(RSTRING_PTR(path), mode) == -1)
if (rb_chmod(RSTRING_PTR(path), mode) == -1)
rb_sys_fail_path(fptr->pathv);
#endif

Expand Down Expand Up @@ -2709,6 +2755,51 @@ rb_file_s_chown(int argc, VALUE *argv, VALUE _)
return apply2files(chown_internal, argc, argv, &arg);
}

struct nogvl_chown_data {
union {
const char *path;
int fd;
} as;
struct chown_args new;
};

static void *
nogvl_chown(void *ptr)
{
struct nogvl_chown_data *data = ptr;
return (void *)(VALUE)chown(data->as.path, data->new.owner, data->new.group);
}

static int
rb_chown(const char *path, rb_uid_t owner, rb_gid_t group)
{
struct nogvl_chown_data data = {
.as = {.path = path},
.new = {.owner = owner, .group = group},
};
return IO_WITHOUT_GVL_INT(nogvl_chown, &data);
}

#ifdef HAVE_FCHOWN
static void *
nogvl_fchown(void *ptr)
{
struct nogvl_chown_data *data = ptr;
return (void *)(VALUE)fchown(data->as.fd, data->new.owner, data->new.group);
}

static int
rb_fchown(int fd, rb_uid_t owner, rb_gid_t group)
{
(void)rb_chown; /* suppress unused-function warning when HAVE_FCHMOD */
struct nogvl_chown_data data = {
.as = {.fd = fd},
.new = {.owner = owner, .group = group},
};
return IO_WITHOUT_GVL_INT(nogvl_fchown, &data);
}
#endif

/*
* call-seq:
* file.chown(owner_int, group_int ) -> 0
Expand Down Expand Up @@ -2740,10 +2831,10 @@ rb_file_chown(VALUE obj, VALUE owner, VALUE group)
#ifndef HAVE_FCHOWN
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
if (chown(RSTRING_PTR(path), o, g) == -1)
if (rb_chown(RSTRING_PTR(path), o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#else
if (fchown(fptr->fd, o, g) == -1)
if (rb_fchown(fptr->fd, o, g) == -1)
rb_sys_fail_path(fptr->pathv);
#endif

Expand Down