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
Merge pull request #2974 from nguerrera/shim-pipe
Browse files Browse the repository at this point in the history
Shim pipe and fcntl
  • Loading branch information
stephentoub committed Aug 27, 2015
2 parents a41674d + 73502c9 commit 86d077f
Show file tree
Hide file tree
Showing 17 changed files with 230 additions and 171 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
}
}
2 changes: 1 addition & 1 deletion src/Common/src/Interop/Unix/System.Native/Interop.Stat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ internal enum FileStatusFlags
}

[DllImport(Libraries.SystemNative, SetLastError = true)]
internal static extern int FStat(int fileDescriptor, out FileStatus output);
internal static extern int FStat(int fd, out FileStatus output);

[DllImport(Libraries.SystemNative, SetLastError = true)]
internal static extern int Stat(string path, out FileStatus output);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ internal struct DirectoryEntry
private static unsafe extern int ReadDirR(SafeDirectoryHandle dir, byte* buffer, int bufferSize, out InternalDirectoryEntry outputEntry);

[DllImport(Libraries.SystemNative, SetLastError = true)]
internal static extern int CloseDir(IntPtr directory);
internal static extern int CloseDir(IntPtr dir);

// The calling pattern for ReadDir is described in src/Native/System.Native/pal_readdir.cpp
internal static int ReadDir(SafeDirectoryHandle dir, out DirectoryEntry outputEntry)
Expand Down
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
68 changes: 61 additions & 7 deletions src/Native/System.Native/pal_io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ int32_t Stat(const char* path, FileStatus* output)
}

extern "C"
int32_t FStat(int32_t fileDescriptor, FileStatus* output)
int32_t FStat(int32_t fd, FileStatus* output)
{
struct stat_ result;
int ret = fstat_(fileDescriptor, &result);
int ret = fstat_(fd, &result);

if (ret == 0)
{
Expand Down Expand Up @@ -185,9 +185,9 @@ int32_t Open(const char* path, int32_t flags, int32_t mode)
}

extern "C"
int32_t Close(int32_t fileDescriptor)
int32_t Close(int32_t fd)
{
return close(fileDescriptor);
return close(fd);
}

extern "C"
Expand Down Expand Up @@ -215,7 +215,6 @@ int32_t ShmUnlink(const char* name)
return shm_unlink(name);
}


static
void ConvertDirent(const dirent& entry, DirectoryEntry* outputEntry)
{
Expand Down Expand Up @@ -299,7 +298,62 @@ DIR* OpenDir(const char* path)
}

extern "C"
int32_t CloseDir(DIR* directory)
int32_t CloseDir(DIR* dir)
{
return closedir(dir);
}

extern "C"
int32_t Pipe(int32_t pipeFds[2], int32_t flags)
{
return closedir(directory);
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
}
69 changes: 59 additions & 10 deletions src/Native/System.Native/pal_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ struct DirectoryEntry
*/
extern "C"
int32_t FStat(
int32_t fileDescriptor,
int32_t fd,
FileStatus* output);

/**
Expand Down Expand Up @@ -160,7 +160,7 @@ int32_t LStat(
extern "C"
int32_t Open(
const char* path,
int32_t oflag,
int32_t flags,
int32_t mode);

/**
Expand All @@ -170,8 +170,8 @@ int32_t Open(
*/
extern "C"
int32_t Close(
int32_t fileDescriptor);
int32_t fd);

/**
* Delete an entry from the file system. Implemented as shim to unlink(2).
*
Expand All @@ -180,17 +180,17 @@ int32_t Close(
extern "C"
int32_t Unlink(
const char* path);

/**
* Open or create a shared memory object. Implemented as shim to shm_open(3).
*
* Returns file descriptor or -1 on fiailure. Sets errno on failure.
*/
extern "C"
int32_t ShmOpen(
const char* name,
int32_t oflag,
int32_t mode);
const char* name,
int32_t flags,
int32_t mode);

/**
* Unlink a shared memory object. Implemented as shim to shm_unlink(3).
Expand Down Expand Up @@ -223,10 +223,59 @@ int32_t ReadDirR(
* Returns a DIR struct containing info about the current path or NULL on failure; sets errno on fail.
*/
extern "C"
DIR* OpenDir(const char* path);
DIR* OpenDir(
const char* path);

/**
* Closes the directory stream opened by opendir and returns 0 on success. On fail, -1 is returned and errno is set
*/
extern "C"
int32_t CloseDir(DIR* directory);
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);
Loading

0 comments on commit 86d077f

Please sign in to comment.