// io_reopen
protected RubyIO reopenIO(ThreadContext context, RubyIO nfile) {
Ruby runtime = context.runtime;
OpenFile fptr, orig;
ChannelFD fd, fd2;
long pos = 0;
nfile = TypeConverter.ioGetIO(runtime, nfile);
fptr = getOpenFileChecked();
orig = nfile.getOpenFileChecked();
if (fptr == orig) return this;
if (fptr.IS_PREP_STDIO()) {
if ((fptr.stdio_file == System.in && !orig.isReadable()) ||
(fptr.stdio_file == System.out && !orig.isWritable()) ||
(fptr.stdio_file == System.err && !orig.isWritable())) {
throw runtime.newArgumentError(fptr.PREP_STDIO_NAME() + " can't change access mode from \"" + fptr.getModeAsString(runtime) + "\" to \"" + orig.getModeAsString(runtime) + "\"");
}
}
// FIXME: three lock acquires...trying to reduce risk of deadlock, but not sure it's possible.
boolean locked = fptr.lock();
try {
if (fptr.isWritable()) {
if (fptr.io_fflush(context) < 0)
throw runtime.newErrnoFromErrno(fptr.errno(), fptr.getPath());
} else {
fptr.tell(context);
}
} finally {
if (locked) fptr.unlock();
}
locked = orig.lock();
try {
if (orig.isReadable()) {
pos = orig.tell(context);
}
if (orig.isWritable()) {
if (orig.io_fflush(context) < 0)
throw runtime.newErrnoFromErrno(orig.errno(), fptr.getPath());
}
} finally {
if (locked) orig.unlock();
}
/* copy rb_io_t structure */
// NOTE: MRI does not copy sync here, but I can find no way to make stdout/stderr stay sync through a reopen
locked = fptr.lock();
boolean locked2 = orig.lock(); // TODO: This WILL deadlock if two threads try to reopen the same IOs in opposite directions. Fix?
try {
fptr.setMode(orig.getMode() | (fptr.getMode() & (OpenFile.PREP | OpenFile.SYNC)));
fptr.setProcess(orig.getProcess());
fptr.setLineNumber(orig.getLineNumber());
if (orig.getPath() != null) fptr.setPath(orig.getPath());
else if (!fptr.IS_PREP_STDIO()) fptr.setPath(null);
fptr.setFinalizer(orig.getFinalizer());
// TODO: unsure what to do here
// #if defined (__CYGWIN__) || !defined(HAVE_FORK)
// if (fptr->finalize == pipe_finalize)
// pipe_add_fptr(fptr);
// #endif
fd = fptr.fd();
fd2 = orig.fd();
if (fd != fd2) {
if (fptr.IS_PREP_STDIO() || fd.bestFileno() <= 2 || fptr.stdio_file == null) {
/* need to keep FILE objects of stdin, stdout and stderr */
checkReopenCloexecDup2(runtime, orig, fd2, fd);
// rb_update_max_fd(fd);
fptr.setFD(fd);