diff options
author | Henric Müller <hemuller@microsoft.com> | 2016-10-12 16:04:10 +0300 |
---|---|---|
committer | Henric Müller <hemuller@microsoft.com> | 2016-10-12 16:07:04 +0300 |
commit | 0aed701c96bfc3880076f2dcc53ef7fc2f749c9c (patch) | |
tree | f3a4bd1d7a9ea669b4fba504c5f997950a39f143 /mcs/class/System.Runtime.Remoting | |
parent | 082057e3d7247ac5c260355d8145960fbaaa8e76 (diff) |
Making named pipe connects alertable on Windows
This fix makes sure that an aborted thread will wake up
a blocking named pipe connect.
Diffstat (limited to 'mcs/class/System.Runtime.Remoting')
2 files changed, 38 insertions, 21 deletions
diff --git a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs index 089cd330b62..974caaaaa8b 100644 --- a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs +++ b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeHelper.cs @@ -26,10 +26,9 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // - -using System; using System.Runtime.InteropServices; using System.Text; +using System.Threading; namespace System.Runtime.Remoting.Channels.Ipc.Win32 { @@ -89,6 +88,7 @@ namespace System.Runtime.Remoting.Channels.Ipc.Win32 public const uint OPEN_EXISTING = 3; public const uint OPEN_ALWAYS = 4; public const uint TRUNCATE_EXISTING = 5; + public const uint FILE_FLAG_OVERLAPPED = 0x40000000; // Access flags public const uint GENERIC_READ = 0x80000000; @@ -103,6 +103,7 @@ namespace System.Runtime.Remoting.Channels.Ipc.Win32 public const int ERROR_PIPE_NOT_CONNECTED = 233; public const int ERROR_PIPE_CONNECTED = 535; public const int ERROR_PIPE_LISTENING = 536; + public const int ERROR_IO_PENDING = 997; public const int INVALID_HANDLE_VALUE = -1; @@ -121,7 +122,7 @@ namespace System.Runtime.Remoting.Channels.Ipc.Win32 [DllImport("kernel32.dll", SetLastError = true)] public static extern bool ConnectNamedPipe( IntPtr hPipe, - IntPtr lpOverlapped + [In] ref NativeOverlapped lpOverlapped ); [DllImport("kernel32.dll", SetLastError = true)] diff --git a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs index 8270e3d157f..7170b7e932a 100644 --- a/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs +++ b/mcs/class/System.Runtime.Remoting/System.Runtime.Remoting.Channels.Ipc.Win32/NamedPipeListener.cs @@ -27,8 +27,8 @@ // -using System; using System.Runtime.InteropServices; +using System.Threading; namespace System.Runtime.Remoting.Channels.Ipc.Win32 { @@ -74,7 +74,7 @@ namespace System.Runtime.Remoting.Channels.Ipc.Win32 { IntPtr hPipe = NamedPipeHelper.CreateNamedPipe( pipeName, - NamedPipeHelper.PIPE_ACCESS_DUPLEX, + NamedPipeHelper.PIPE_ACCESS_DUPLEX | NamedPipeHelper.FILE_FLAG_OVERLAPPED, NamedPipeHelper.PIPE_TYPE_MESSAGE | NamedPipeHelper.PIPE_READMODE_MESSAGE | NamedPipeHelper.PIPE_WAIT, @@ -85,27 +85,43 @@ namespace System.Runtime.Remoting.Channels.Ipc.Win32 IntPtr.Zero ); - if (hPipe.ToInt32() == NamedPipeHelper.INVALID_HANDLE_VALUE) - { - throw new NamedPipeException(); + if (hPipe.ToInt32 () == NamedPipeHelper.INVALID_HANDLE_VALUE) { + throw new NamedPipeException (Marshal.GetLastWin32Error ()); } - bool canConnect = NamedPipeHelper.ConnectNamedPipe(hPipe, IntPtr.Zero); - int lastError = Marshal.GetLastWin32Error(); - if (!canConnect && lastError == NamedPipeHelper.ERROR_PIPE_CONNECTED) - canConnect = true; + // Connect the named pipe with overlapped structure + // in order to make it altertable. This way we will + // wake up when someone aborts a thread waiting + // for this pipe. + NativeOverlapped overlapped = new NativeOverlapped (); + bool canConnect = NamedPipeHelper.ConnectNamedPipe (hPipe, ref overlapped); - if (canConnect) - { - return new NamedPipeSocket(hPipe); - } - else - { - NamedPipeHelper.CloseHandle(hPipe); - throw new NamedPipeException(lastError); - } + int lastError = Marshal.GetLastWin32Error (); + if (!canConnect) { + if (lastError == NamedPipeHelper.ERROR_IO_PENDING) { + uint bytesTransferred = 0; + if (!GetOverlappedResultEx (hPipe, ref overlapped, out bytesTransferred, Timeout.Infinite, true)) { + lastError = Marshal.GetLastWin32Error (); + NamedPipeHelper.CloseHandle (hPipe); + throw new NamedPipeException (lastError); + } + canConnect = true; + } else if (lastError == NamedPipeHelper.ERROR_PIPE_CONNECTED) + canConnect = true; + } + + if (!canConnect) { + NamedPipeHelper.CloseHandle (hPipe); + throw new NamedPipeException (lastError); + } + + return new NamedPipeSocket (hPipe); } + [DllImport("kernel32.dll", SetLastError = true)] + static extern bool GetOverlappedResultEx (IntPtr hFile, [In] ref System.Threading.NativeOverlapped lpOverlapped, + out uint lpNumberOfBytesTransferred, int dwMilliseconds, bool bAltertable); + } } |