Skip to content

Commit dabb6c4

Browse files
authored
Release GVL around {,f}getattrlist calls in dir.c
Fixes [Bug #20587]
1 parent c083a3f commit dabb6c4

File tree

1 file changed

+77
-11
lines changed

1 file changed

+77
-11
lines changed

dir.c

+77-11
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,47 @@ char *strchr(char*,char);
143143
# define IS_WIN32 0
144144
#endif
145145

146+
#ifdef HAVE_GETATTRLIST
147+
struct getattrlist_args {
148+
const char *path;
149+
int fd;
150+
struct attrlist *list;
151+
void *buf;
152+
size_t size;
153+
unsigned int options;
154+
};
155+
156+
static void *
157+
nogvl_getattrlist(void *args)
158+
{
159+
struct getattrlist_args *arg = args;
160+
return (void *)(VALUE)getattrlist(arg->path, arg->list, arg->buf, arg->size, arg->options);
161+
}
162+
163+
static int
164+
gvl_getattrlist(struct getattrlist_args *args, const char *path)
165+
{
166+
args->path = path;
167+
return IO_WITHOUT_GVL_INT(nogvl_getattrlist, args);
168+
}
169+
170+
# ifdef HAVE_FGETATTRLIST
171+
static void *
172+
nogvl_fgetattrlist(void *args)
173+
{
174+
struct getattrlist_args *arg = args;
175+
return (void *)(VALUE)fgetattrlist(arg->fd, arg->list, arg->buf, arg->size, arg->options);
176+
}
177+
178+
static int
179+
gvl_fgetattrlist(struct getattrlist_args *args, int fd)
180+
{
181+
args->fd = fd;
182+
return IO_WITHOUT_GVL_INT(nogvl_fgetattrlist, args);
183+
}
184+
# endif
185+
#endif
186+
146187
#if NORMALIZE_UTF8PATH
147188
# if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST
148189
# define need_normalization(dirp, path) need_normalization(dirp)
@@ -155,10 +196,15 @@ need_normalization(DIR *dirp, const char *path)
155196
# if defined HAVE_FGETATTRLIST || defined HAVE_GETATTRLIST
156197
u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
157198
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
199+
struct getattrlist_args args;
200+
args.list = &al;
201+
args.buf = attrbuf;
202+
args.size = sizeof(attrbuf);
203+
args.options = 0;
158204
# if defined HAVE_FGETATTRLIST
159-
int ret = fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), 0);
205+
int ret = gvl_fgetattrlist(&args, dirfd(dirp));
160206
# else
161-
int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0);
207+
int ret = gvl_getattrlist(&args, path);
162208
# endif
163209
if (!ret) {
164210
const fsobj_tag_t *tag = (void *)(attrbuf+1);
@@ -555,7 +601,12 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
555601
else if (e == EIO) {
556602
u_int32_t attrbuf[1];
557603
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
558-
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
604+
struct getattrlist_args args;
605+
args.list = &al;
606+
args.buf = attrbuf;
607+
args.size = sizeof(attrbuf);
608+
args.options = FSOPT_NOFOLLOW;
609+
if (gvl_getattrlist(&args, path) == 0) {
559610
dp->dir = opendir_without_gvl(path);
560611
}
561612
}
@@ -2134,14 +2185,19 @@ is_case_sensitive(DIR *dirp, const char *path)
21342185
const vol_capabilities_attr_t *const cap = attrbuf[0].cap;
21352186
const int idx = VOL_CAPABILITIES_FORMAT;
21362187
const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE;
2137-
2188+
struct getattrlist_args args;
2189+
args.list = &al;
2190+
args.buf = attrbuf;
2191+
args.size = sizeof(attrbuf);
2192+
args.options = FSOPT_NOFOLLOW;
21382193
# if defined HAVE_FGETATTRLIST
2139-
if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
2140-
return -1;
2194+
int ret = gvl_fgetattrlist(&args, dirfd(dirp));
21412195
# else
2142-
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
2143-
return -1;
2196+
int ret = gvl_getattrlist(&args, path);
21442197
# endif
2198+
if (ret)
2199+
return -1;
2200+
21452201
if (!(cap->valid[idx] & mask))
21462202
return -1;
21472203
return (cap->capabilities[idx] & mask) != 0;
@@ -2164,7 +2220,12 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
21642220
IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
21652221

21662222
*type = path_noent;
2167-
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) {
2223+
struct getattrlist_args args;
2224+
args.list = &al;
2225+
args.buf = attrbuf;
2226+
args.size = sizeof(attrbuf);
2227+
args.options = FSOPT_NOFOLLOW;
2228+
if (gvl_getattrlist(&args, path)) {
21682229
if (!to_be_ignored(errno))
21692230
sys_warning(path, enc);
21702231
return path;
@@ -3700,12 +3761,17 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname)
37003761
{
37013762
u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
37023763
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
3703-
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0)
3764+
struct getattrlist_args args;
3765+
args.list = &al;
3766+
args.buf = attrbuf;
3767+
args.size = sizeof(attrbuf);
3768+
args.options = 0;
3769+
if (gvl_getattrlist(&args, path) != 0)
37043770
rb_sys_fail_path(orig);
37053771
if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
37063772
al.commonattr = 0;
37073773
al.dirattr = ATTR_DIR_ENTRYCOUNT;
3708-
if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) {
3774+
if (gvl_getattrlist(&args, path) == 0) {
37093775
if (attrbuf[0] >= 2 * sizeof(u_int32_t))
37103776
return RBOOL(attrbuf[1] == 0);
37113777
if (false_on_notdir) return Qfalse;

0 commit comments

Comments
 (0)