summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-07 14:05:38 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-07 14:05:38 +0000
commit2921521e9215652e07af266b1870543f2e5b229c (patch)
tree85a6a5be18304aff1ef829ecd509ebe8e735d1b9 /io.c
parent6d742295f3f75630234c393484445fa287cf02a1 (diff)
merge revision(s) 60055: [Backport #13856]
io.c: fix segfault with closing socket on Windows * io.c (fptr_finalize_flush): add an argument to keep GVL. * io.c (fptr_finalize): adjust for above change. * io.c (io_close_fptr): closing without GVL causes another exception while raising exception in another thread. This causes segfault on Windows. Keep GVL while closing when another thread raises. [Bug #13856] [ruby-core:82602] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62690 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/io.c b/io.c
index ee3ea3e68a..2847980610 100644
--- a/io.c
+++ b/io.c
@@ -4277,7 +4277,7 @@ static void free_io_buffer(rb_io_buffer_t *buf);
static void clear_codeconv(rb_io_t *fptr);
static void
-fptr_finalize_flush(rb_io_t *fptr, int noraise)
+fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl)
{
VALUE err = Qnil;
int fd = fptr->fd;
@@ -4325,7 +4325,7 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise)
* We assumes it is closed. */
/**/
- int keepgvl = !(mode & FMODE_WRITABLE);
+ keepgvl |= !(mode & FMODE_WRITABLE);
keepgvl |= noraise;
if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
err = noraise ? Qtrue : INT2NUM(errno);
@@ -4342,7 +4342,7 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise)
static void
fptr_finalize(rb_io_t *fptr, int noraise)
{
- fptr_finalize_flush(fptr, noraise);
+ fptr_finalize_flush(fptr, noraise, FALSE);
free_io_buffer(&fptr->rbuf);
free_io_buffer(&fptr->wbuf);
clear_codeconv(fptr);
@@ -4422,6 +4422,13 @@ rb_io_memsize(const rb_io_t *fptr)
return size;
}
+#ifdef _WIN32
+/* keep GVL while closing to prevent crash on Windows */
+# define KEEPGVL TRUE
+#else
+# define KEEPGVL FALSE
+#endif
+
int rb_notify_fd_close(int fd);
static rb_io_t *
io_close_fptr(VALUE io)
@@ -4446,8 +4453,8 @@ io_close_fptr(VALUE io)
fd = fptr->fd;
busy = rb_notify_fd_close(fd);
- fptr_finalize_flush(fptr, FALSE);
if (busy) {
+ fptr_finalize_flush(fptr, FALSE, KEEPGVL);
do rb_thread_schedule(); while (rb_notify_fd_close(fd));
}
rb_io_fptr_cleanup(fptr, FALSE);