@@ -11458,6 +11458,37 @@ pm_parse_file_script_lines(const pm_scope_node_t *scope_node, const pm_parser_t
1145811458 return lines ;
1145911459}
1146011460
11461+ struct load_from_fd_args {
11462+ VALUE path ;
11463+ VALUE io ;
11464+ int open_mode ;
11465+ int fd ;
11466+ };
11467+
11468+ static VALUE
11469+ close_file (VALUE args )
11470+ {
11471+ struct load_from_fd_args * arg = (void * )args ;
11472+ if (arg -> fd != -1 ) {
11473+ close (arg -> fd );
11474+ }
11475+ else if (!NIL_P (arg -> io )) {
11476+ rb_io_close (arg -> io );
11477+ }
11478+ return Qnil ;
11479+ }
11480+
11481+ static VALUE
11482+ load_content (VALUE args )
11483+ {
11484+ struct load_from_fd_args * arg = (void * )args ;
11485+ VALUE io = rb_io_fdopen (arg -> fd , arg -> open_mode , RSTRING_PTR (arg -> path ));
11486+ arg -> io = io ;
11487+ arg -> fd = -1 ;
11488+ rb_io_wait (io , RB_INT2NUM (RUBY_IO_READABLE ), Qnil );
11489+ return rb_funcall (io , rb_intern ("read" ), 0 );
11490+ }
11491+
1146111492/**
1146211493 * Attempt to load the file into memory. Return a Ruby error if the file cannot
1146311494 * be read.
@@ -11478,13 +11509,14 @@ pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error)
1147811509 // For non-regular files (pipes, character devices), we need to read
1147911510 // through Ruby IO to properly release the GVL while waiting for data.
1148011511 if (init_result == PM_SOURCE_INIT_ERROR_NON_REGULAR ) {
11481- const int open_mode = O_RDONLY | O_NONBLOCK ;
11482- int fd = open (RSTRING_PTR (filepath ), open_mode );
11483- if (fd == -1 ) goto error_generic ;
11484-
11485- VALUE io = rb_io_fdopen (fd , open_mode , RSTRING_PTR (filepath ));
11486- rb_io_wait (io , RB_INT2NUM (RUBY_IO_READABLE ), Qnil );
11487- VALUE contents = rb_funcall (io , rb_intern ("read" ), 0 );
11512+ struct load_from_fd_args args = {
11513+ .path = filepath ,
11514+ .open_mode = O_RDONLY | O_NONBLOCK ,
11515+ .fd = rb_cloexec_open (RSTRING_PTR (filepath ), args .open_mode , 0 ),
11516+ .io = Qnil ,
11517+ };
11518+ if (args .fd == -1 ) goto error_generic ;
11519+ VALUE contents = rb_ensure (load_content , (VALUE )& args , close_file , (VALUE )& args );
1148811520
1148911521 if (!RB_TYPE_P (contents , T_STRING )) goto error_generic ;
1149011522
0 commit comments