Skip to content

Commit cce8776

Browse files
committedJan 24, 2018
Fix PTY by being more permissive of fcntl flags. Fixes #5004.
Note that this logic is still wrong when attempting to clear flags since it only looks for them to be set. We should mimic CRuby's fcntl logic when we have access to a real file descriptor, and use the current logic (with fixes for clearing flags) as a fallback only.
1 parent 6b375fd commit cce8776

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed
 

‎core/src/main/java/org/jruby/RubyIO.java

+18-11
Original file line numberDiff line numberDiff line change
@@ -2439,12 +2439,12 @@ public void setBlocking(boolean blocking) {
24392439

24402440
@JRubyMethod(name = "fcntl")
24412441
public IRubyObject fcntl(ThreadContext context, IRubyObject cmd) {
2442-
return ctl(context.runtime, cmd, null);
2442+
return ctl(context, cmd, null);
24432443
}
24442444

24452445
@JRubyMethod(name = "fcntl")
24462446
public IRubyObject fcntl(ThreadContext context, IRubyObject cmd, IRubyObject arg) {
2447-
return ctl(context.runtime, cmd, arg);
2447+
return ctl(context, cmd, arg);
24482448
}
24492449

24502450
@JRubyMethod(name = "ioctl", required = 1, optional = 1)
@@ -2458,10 +2458,11 @@ public IRubyObject ioctl(ThreadContext context, IRubyObject[] args) {
24582458
arg = context.runtime.getNil();
24592459
}
24602460

2461-
return ctl(context.runtime, cmd, arg);
2461+
return ctl(context, cmd, arg);
24622462
}
24632463

2464-
private IRubyObject ctl(Ruby runtime, IRubyObject cmd, IRubyObject arg) {
2464+
private IRubyObject ctl(ThreadContext context, IRubyObject cmd, IRubyObject arg) {
2465+
Ruby runtime = context.runtime;
24652466
long realCmd = cmd.convertToInteger().getLongValue();
24662467
long nArg = 0;
24672468

@@ -2494,25 +2495,31 @@ private IRubyObject ctl(Ruby runtime, IRubyObject cmd, IRubyObject arg) {
24942495
// for mode changes which should persist across fork() boundaries. Since JVM has no fork
24952496
// this is not a problem for us.
24962497
if (realCmd == FcntlLibrary.FD_CLOEXEC) {
2497-
close_on_exec_set(runtime.getCurrentContext(), runtime.getTrue());
2498+
close_on_exec_set(context, runtime.getTrue());
24982499
} else if (realCmd == Fcntl.F_SETFD.intValue()) {
24992500
if (arg != null && (nArg & FcntlLibrary.FD_CLOEXEC) == FcntlLibrary.FD_CLOEXEC) {
2500-
close_on_exec_set(runtime.getCurrentContext(), arg);
2501+
close_on_exec_set(context, arg);
25012502
} else {
25022503
throw runtime.newNotImplementedError("F_SETFD only supports FD_CLOEXEC");
25032504
}
25042505
} else if (realCmd == Fcntl.F_GETFD.intValue()) {
2505-
return runtime.newFixnum(close_on_exec_p(runtime.getCurrentContext()).isTrue() ? FD_CLOEXEC : 0);
2506+
return runtime.newFixnum(close_on_exec_p(context).isTrue() ? FD_CLOEXEC : 0);
25062507
} else if (realCmd == Fcntl.F_SETFL.intValue()) {
25072508
if ((nArg & OpenFlags.O_NONBLOCK.intValue()) != 0) {
2508-
boolean block = (nArg & ModeFlags.NONBLOCK) != ModeFlags.NONBLOCK;
2509+
fptr.setBlocking(runtime, true);
2510+
} else {
2511+
fptr.setBlocking(runtime, false);
2512+
}
25092513

2510-
fptr.setBlocking(runtime, block);
2514+
if ((nArg & OpenFlags.O_CLOEXEC.intValue()) != 0) {
2515+
close_on_exec_set(context, context.tru);
25112516
} else {
2512-
throw runtime.newNotImplementedError("F_SETFL only supports O_NONBLOCK");
2517+
close_on_exec_set(context, context.fals);
25132518
}
25142519
} else if (realCmd == Fcntl.F_GETFL.intValue()) {
2515-
return fptr.isBlocking() ? RubyFixnum.zero(runtime) : RubyFixnum.newFixnum(runtime, ModeFlags.NONBLOCK);
2520+
return runtime.newFixnum(
2521+
(fptr.isBlocking() ? 0 : OpenFlags.O_NONBLOCK.intValue()) |
2522+
(close_on_exec_p(context).isTrue() ? FD_CLOEXEC : 0));
25162523
} else {
25172524
throw runtime.newNotImplementedError("JRuby only supports F_SETFL and F_GETFL with NONBLOCK for fcntl/ioctl");
25182525
}

0 commit comments

Comments
 (0)
Please sign in to comment.