Skip to content

Commit 827caee

Browse files
committed
Use genuine file descriptors on Unix
1 parent 8504f29 commit 827caee

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

Src/IronPython.Modules/nt.cs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,18 @@ public static int dup(CodeContext/*!*/ context, int fd) {
353353
StreamBox streams = fileManager.GetStreams(fd); // OSError if fd not valid
354354
fileManager.EnsureRefStreams(streams);
355355
fileManager.AddRefStreams(streams);
356-
return fileManager.Add(new(streams));
356+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
357+
return fileManager.Add(new(streams));
358+
} else {
359+
return fileManager.Add(UnixDup(fd), new(streams));
360+
}
361+
362+
// Isolate Mono.Unix from the rest of the method so that we don't try to load the Mono.Unix assembly on Windows.
363+
static int UnixDup(int fd) {
364+
int res = Mono.Unix.Native.Syscall.dup(fd);
365+
if (res < 0) throw GetLastUnixError();
366+
return res;
367+
}
357368
}
358369

359370

@@ -377,7 +388,18 @@ public static int dup2(CodeContext/*!*/ context, int fd, int fd2) {
377388

378389
fileManager.EnsureRefStreams(streams);
379390
fileManager.AddRefStreams(streams);
380-
return fileManager.Add(fd2, new(streams));
391+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
392+
return fileManager.Add(fd2, new(streams));
393+
} else {
394+
return fileManager.Add(UnixDup2(fd, fd2), new(streams));
395+
}
396+
397+
// Isolate Mono.Unix from the rest of the method so that we don't try to load the Mono.Unix assembly on Windows.
398+
static int UnixDup2(int fd, int fd2) {
399+
int res = Mono.Unix.Native.Syscall.dup2(fd, fd2);
400+
if (res < 0) throw GetLastUnixError();
401+
return res;
402+
}
381403
}
382404

383405
#if FEATURE_PROCESS
@@ -842,7 +864,11 @@ public static object open(CodeContext/*!*/ context, [NotNone] string path, int f
842864
fs = new FileStream(path, fileMode, access, FileShare.ReadWrite, DefaultBufferSize, options);
843865
}
844866

845-
return context.LanguageContext.FileManager.Add(new(fs));
867+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
868+
return context.LanguageContext.FileManager.Add(new(fs));
869+
} else {
870+
return context.LanguageContext.FileManager.Add((int)fs.SafeFileHandle.DangerousGetHandle(), new(fs));
871+
}
846872
} catch (Exception e) {
847873
throw ToPythonException(e, path);
848874
}
@@ -877,30 +903,29 @@ private static FileOptions FileOptionsFromFlags(int flag) {
877903

878904
#if FEATURE_PIPES
879905

880-
private static Tuple<Stream, Stream> CreatePipeStreams() {
881-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
882-
return CreatePipeStreamsUnix();
883-
} else {
906+
public static PythonTuple pipe(CodeContext context) {
907+
var manager = context.LanguageContext.FileManager;
908+
909+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
884910
var inPipe = new AnonymousPipeServerStream(PipeDirection.In);
885911
var outPipe = new AnonymousPipeClientStream(PipeDirection.Out, inPipe.ClientSafePipeHandle);
886-
return Tuple.Create<Stream, Stream>(inPipe, outPipe);
912+
return PythonTuple.MakeTuple(
913+
manager.Add(new(inPipe)),
914+
manager.Add(new(outPipe))
915+
);
916+
} else {
917+
var pipeStreams = CreatePipeStreamsUnix();
918+
return PythonTuple.MakeTuple(
919+
manager.Add((int)pipeStreams.Item1.SafeFileHandle.DangerousGetHandle(), new(pipeStreams.Item1)),
920+
manager.Add((int)pipeStreams.Item2.SafeFileHandle.DangerousGetHandle(), new(pipeStreams.Item2))
921+
);
887922
}
888923

889924
static Tuple<Stream, Stream> CreatePipeStreamsUnix() {
890925
Mono.Unix.UnixPipes pipes = Mono.Unix.UnixPipes.CreatePipes();
891926
return Tuple.Create<Stream, Stream>(pipes.Reading, pipes.Writing);
892927
}
893928
}
894-
895-
public static PythonTuple pipe(CodeContext context) {
896-
var pipeStreams = CreatePipeStreams();
897-
var manager = context.LanguageContext.FileManager;
898-
899-
return PythonTuple.MakeTuple(
900-
manager.Add(new(pipeStreams.Item1)),
901-
manager.Add(new(pipeStreams.Item2))
902-
);
903-
}
904929
#endif
905930

906931
#if FEATURE_PROCESS

Src/IronPython/Runtime/PythonFileManager.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Collections.Generic;
1111
using System.Diagnostics.CodeAnalysis;
1212
using System.IO;
13+
using System.Runtime.Versioning;
1314

1415
using Microsoft.Scripting.Runtime;
1516
using Microsoft.Scripting.Utils;
@@ -212,6 +213,7 @@ internal class PythonFileManager {
212213
private int _current = _offset; // lowest potentially unused key in _objects at or above _offset
213214
private readonly ConcurrentDictionary<Stream, int> _refs = new();
214215

216+
// Mandatory Add for Unix, on Windows only for dup2 case
215217
public int Add(int id, StreamBox streams) {
216218
ContractUtils.RequiresNotNull(streams, nameof(streams));
217219
ContractUtils.Requires(streams.Id < 0, nameof(streams));
@@ -226,6 +228,7 @@ public int Add(int id, StreamBox streams) {
226228
}
227229
}
228230

231+
[SupportedOSPlatform("windows")]
229232
public int Add(StreamBox streams) {
230233
ContractUtils.RequiresNotNull(streams, nameof(streams));
231234
ContractUtils.Requires(streams.Id < 0, nameof(streams));

0 commit comments

Comments
 (0)