Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Shim pipe and fcntl
Browse files Browse the repository at this point in the history
  • Loading branch information
nguerrera committed Aug 26, 2015
1 parent 590bcde commit 73502c9
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 152 deletions.
15 changes: 0 additions & 15 deletions src/Common/src/Interop/Linux/libc/Interop.FcntlCommands.cs

This file was deleted.

20 changes: 0 additions & 20 deletions src/Common/src/Interop/Linux/libc/Interop.pipe2.cs

This file was deleted.

25 changes: 25 additions & 0 deletions src/Common/src/Interop/Unix/System.Native/Interop.Fcntl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Sys
{
internal static class Fcntl
{
internal static readonly bool CanGetSetPipeSz = (FcntlCanGetSetPipeSz() != 0);

[DllImport(Libraries.SystemNative, EntryPoint="FcntlGetPipeSz", SetLastError=true)]
internal static extern int GetPipeSz(int fd);

[DllImport(Libraries.SystemNative, EntryPoint="FcntlSetPipeSz", SetLastError=true)]
internal static extern int SetPipeSz(int fd, int size);

[DllImport(Libraries.SystemNative)]
private static extern int FcntlCanGetSetPipeSz();
}
}
}
30 changes: 30 additions & 0 deletions src/Common/src/Interop/Unix/System.Native/Interop.Pipe.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Sys
{
[Flags]
internal enum PipeFlags
{
O_CLOEXEC = 0x0010,
}

/// <summary>
/// The index into the array filled by <see cref="pipe"/> which represents the read end of the pipe.
/// </summary>
internal const int ReadEndOfPipe = 0;

/// <summary>
/// The index into the array filled by <see cref="pipe"/> which represents the read end of the pipe.
/// </summary>
internal const int WriteEndOfPipe = 1;

[DllImport(Libraries.SystemNative, SetLastError = true)]
internal static extern unsafe int Pipe(int* pipefd, PipeFlags flags = 0); // pipefd is an array of two ints
}
}
21 changes: 0 additions & 21 deletions src/Common/src/Interop/Unix/libc/Interop.fcntl.cs

This file was deleted.

12 changes: 6 additions & 6 deletions src/Common/src/Interop/Unix/libcurl/Interop.SafeCurlHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public SafeCurlMultiHandle()
{
fixed(int* fds = _specialFds)
{
while (Interop.CheckIo(libc.pipe(fds)));
while (Interop.CheckIo(Interop.Sys.Pipe(fds)));
}
}
}
Expand Down Expand Up @@ -116,7 +116,7 @@ internal void PollFds(List<libc.pollfd> readyFds)
// is ready for a read/write. The special fd is the read end of a pipe
// Whenever an fd is added/removed in _fdSet, a write happens to the
// write end of the pipe thus causing the poll to return.
pollFds[0].fd = _specialFds[libc.ReadEndOfPipe];
pollFds[0].fd = _specialFds[Interop.Sys.ReadEndOfPipe];
pollFds[0].events = PollFlags.POLLIN;
int i = 1;
foreach (int fd in _fdSet)
Expand Down Expand Up @@ -186,7 +186,7 @@ internal void SignalFdSetChange(int fd, bool isRemove)
{
// Write to special fd
byte* dummyBytes = stackalloc byte[1];
if ((int)libc.write(_specialFds[libc.WriteEndOfPipe], dummyBytes, (size_t)1) <= 0)
if ((int)libc.write(_specialFds[Interop.Sys.WriteEndOfPipe], dummyBytes, (size_t)1) <= 0)
{
// TODO: How to handle errors?
throw new InvalidOperationException("Cannot write data: " + Marshal.GetLastWin32Error());
Expand All @@ -212,8 +212,8 @@ protected override bool ReleaseHandle()
Debug.Assert(0 == _requestCount);
Debug.Assert(_pollCancelled);

Interop.Sys.Close(_specialFds[libc.ReadEndOfPipe]);
Interop.Sys.Close(_specialFds[libc.WriteEndOfPipe]);
Interop.Sys.Close(_specialFds[Interop.Sys.ReadEndOfPipe]);
Interop.Sys.Close(_specialFds[Interop.Sys.WriteEndOfPipe]);
libcurl.curl_multi_cleanup(this.handle);

return true;
Expand All @@ -227,7 +227,7 @@ private int ReadSpecialFd(PollFlags revents)
return -1;
}
Debug.Assert((revents & PollFlags.POLLIN) != 0);
int pipeReadFd = _specialFds[libc.ReadEndOfPipe];
int pipeReadFd = _specialFds[Interop.Sys.ReadEndOfPipe];
int bytesRead = 0;
unsafe
{
Expand Down
55 changes: 55 additions & 0 deletions src/Native/System.Native/pal_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,58 @@ int32_t CloseDir(DIR* dir)
{
return closedir(dir);
}

extern "C"
int32_t Pipe(int32_t pipeFds[2], int32_t flags)
{
switch (flags)
{
case 0:
break;
case PAL_O_CLOEXEC:
flags = O_CLOEXEC;
break;
default:
assert(!"Unknown flag.");
errno = EINVAL;
return -1;
}

#if HAVE_PIPE2
return pipe2(pipeFds, flags);
#else
return pipe(pipeFds); // CLOEXEC intentionally ignored on platforms without pipe2.
#endif
}

extern "C"
int32_t FcntlCanGetSetPipeSz()
{
#if defined(F_GETPIPE_SZ) && defined(F_SETPIPE_SZ)
return true;
#else
return false;
#endif
}

extern "C"
int32_t FcntlGetPipeSz(int32_t fd)
{
#ifdef F_GETPIPE_SZ
return fcntl(fd, F_GETPIPE_SZ);
#else
errno = ENOTSUP;
return -1;
#endif
}

extern "C"
int32_t FcntlSetPipeSz(int32_t fd, int32_t size)
{
#ifdef F_SETPIPE_SZ
return fcntl(fd, F_SETPIPE_SZ, size);
#else
errno = ENOTSUP;
return -1;
#endif
}
47 changes: 47 additions & 0 deletions src/Native/System.Native/pal_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,50 @@ DIR* OpenDir(
extern "C"
int32_t CloseDir(
DIR* dir);

/**
* Creates a pipe. Implemented as shim to pipe(2) or pipe2(2) if available.
* Flags are ignored if pipe2 is not available.
*
* Returns 0 for success, -1 for failure. Sets errno on failure.
*/
extern "C"
int32_t Pipe(
int32_t pipefd[2], // [out] pipefds[0] gets read end, pipefd[1] gets write end.
int32_t flags); // 0 for defaults or PAL_O_CLOEXEC for close-on-exec


// NOTE: Rather than a general fcntl shim, we opt to export separate functions
// for each command. This allows use to have strongly typed arguments and saves
// complexity around converting command codes.

/**
* Determines if the current platform supports getting and setting pipe capacity.
*
* Returns true (non-zero) if supported, false (zero) if not.
*/
extern "C"
int32_t FcntlCanGetSetPipeSz();

/**
* Gets the capacity of a pipe.
*
* Returns the capacity or -1 with errno set aprropriately on failure.
*
* NOTE: Some platforms do not support this operation and will always fail with errno = ENOTSUP.
*/
extern "C"
int32_t FcntlGetPipeSz(
int32_t fd);

/**
* Sets the capacity of a pipe.
*
* Returns 0 for success, -1 for failure. Sets errno for failure.
*
* NOTE: Some platforms do not support this operation and will always fail with errno = ENOTSUP.
*/
extern "C"
int32_t FcntlSetPipeSz(
int32_t fd,
int32_t size);
1 change: 1 addition & 0 deletions src/Native/config.h.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#cmakedefine01 HAVE_STAT64
#cmakedefine01 HAVE_PIPE2
#cmakedefine01 HAVE_STAT_BIRTHTIME
#cmakedefine01 HAVE_GNU_STRERROR_R
#cmakedefine01 HAVE_DIRENT_NAME_LEN
Expand Down
4 changes: 4 additions & 0 deletions src/Native/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ check_function_exists(
stat64
HAVE_STAT64)

check_function_exists(
pipe2
HAVE_PIPE2)

check_struct_has_member(
"struct stat"
st_birthtime
Expand Down
24 changes: 5 additions & 19 deletions src/System.IO.Pipes/src/System.IO.Pipes.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,12 @@
<Compile Include="$(CommonPath)\Interop\Unix\Interop.IOErrors.cs">
<Link>Common\Interop\Unix\Interop.IOErrors.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Linux\libc\Interop.pipe2.cs">
<Link>Common\Interop\Unix\Interop.pipe2.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Close.cs">
<Link>Common\Interop\Unix\Interop.Close.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Fcntl.cs">
<Link>Common\Interop\Unix\Interop.Fcntl.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\libc\Interop.gethostname.cs">
<Link>Common\Interop\Unix\Interop.gethostname.cs</Link>
</Compile>
Expand All @@ -180,8 +180,8 @@
<Compile Include="$(CommonPath)\Interop\Unix\libc\Interop.Permissions.cs">
<Link>Common\Interop\Unix\Interop.Permissions.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\libc\Interop.pipe.cs">
<Link>Common\Interop\Unix\Interop.pipe.cs</Link>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.Pipe.cs">
<Link>Common\Interop\Unix\Interop.Pipe.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\libc\Interop.poll.cs">
<Link>Common\Interop\Unix\Interop.poll.cs</Link>
Expand All @@ -205,20 +205,6 @@
<Link>Common\System\Threading\Tasks\ForceAsyncAwaiter.cs</Link>
</Compile>
</ItemGroup>
<!-- Linux -->
<ItemGroup Condition="'$(TargetsLinux)' == 'true'">
<Compile Include="System\IO\Pipes\PipeStream.Linux.cs" />
<Compile Include="$(CommonPath)\Interop\Unix\libc\Interop.fcntl.cs">
<Link>Common\Interop\Unix\Interop.fcntl.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Linux\libc\Interop.FcntlCommands.cs">
<Link>Common\Interop\Linux\Interop.FcntlCommands.cs</Link>
</Compile>
</ItemGroup>
<!-- OSX -->
<ItemGroup Condition="'$(TargetsOSX)' == 'true'">
<Compile Include="System\IO\Pipes\PipeStream.OSX.cs" />
</ItemGroup>
<!-- Resource files -->
<ItemGroup>
<None Include="project.json" />
Expand Down
40 changes: 0 additions & 40 deletions src/System.IO.Pipes/src/System/IO/Pipes/PipeStream.Linux.cs

This file was deleted.

Loading

0 comments on commit 73502c9

Please sign in to comment.