[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[dotgnu-pnet-commits] pnetlib ChangeLog System/Net/Sockets/Socket.cs ...
From: |
Radek Polak |
Subject: |
[dotgnu-pnet-commits] pnetlib ChangeLog System/Net/Sockets/Socket.cs ... |
Date: |
Fri, 12 Oct 2007 15:10:55 +0000 |
CVSROOT: /sources/dotgnu-pnet
Module name: pnetlib
Changes by: Radek Polak <radekp> 07/10/12 15:10:55
Modified files:
. : ChangeLog
System/Net/Sockets: Socket.cs
Added files:
DotGNU.Misc : BlockingOperation.cs
System/Private : BlockingOperation.cs BlockingOperations.cs
Log message:
fix closing socket by canceling operations that are blocked in system
calls (bug bug #20885)
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnetlib/ChangeLog?cvsroot=dotgnu-pnet&r1=1.2515&r2=1.2516
http://cvs.savannah.gnu.org/viewcvs/pnetlib/DotGNU.Misc/BlockingOperation.cs?cvsroot=dotgnu-pnet&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pnetlib/System/Net/Sockets/Socket.cs?cvsroot=dotgnu-pnet&r1=1.24&r2=1.25
http://cvs.savannah.gnu.org/viewcvs/pnetlib/System/Private/BlockingOperation.cs?cvsroot=dotgnu-pnet&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pnetlib/System/Private/BlockingOperations.cs?cvsroot=dotgnu-pnet&rev=1.1
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/pnetlib/ChangeLog,v
retrieving revision 1.2515
retrieving revision 1.2516
diff -u -b -r1.2515 -r1.2516
--- ChangeLog 9 Oct 2007 12:19:43 -0000 1.2515
+++ ChangeLog 12 Oct 2007 15:10:54 -0000 1.2516
@@ -1,3 +1,17 @@
+2007-10-12 Radek Polak <address@hidden>
+
+ * DotGNU.Misc/BlockingOperation.cs: Class for aborting operations
+ blocked in kernel calls. This can be useful when user is pinvoking
+ kernel calls.
+
+ * System/Private/BlockingOperation.cs,
+ System/Private/BlockingOperations.cs: Helper classes. They are used to
+ abort operations that are blocking in kernel when socket is closed.
+
+ * System/Net/Sockets/Socket.cs: Handle closing correctly by aborting
+ all blocked operations on this socket. This fixes bug #20885.
+
+
2007-10-09 Radek Polak <address@hidden>
* System/IO/Ports/SerialPort.cs: Check return value from write to port
Index: System/Net/Sockets/Socket.cs
===================================================================
RCS file: /sources/dotgnu-pnet/pnetlib/System/Net/Sockets/Socket.cs,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -b -r1.24 -r1.25
--- System/Net/Sockets/Socket.cs 23 Nov 2006 11:05:35 -0000 1.24
+++ System/Net/Sockets/Socket.cs 12 Oct 2007 15:10:55 -0000 1.25
@@ -23,6 +23,7 @@
using Platform;
using System;
+using System.Private;
using System.Collections;
using System.Security;
using System.Threading;
@@ -39,6 +40,7 @@
private EndPoint localEP;
private EndPoint remoteEP;
private Object readLock;
+ private BlockingOperations blockingOps;
// Invalid socket handle.
private static readonly IntPtr InvalidHandle =
@@ -120,6 +122,7 @@
this.localEP = null;
this.remoteEP = null;
this.readLock = new Object();
+ this.blockingOps = new BlockingOperations();
// Attempt to create the socket. This may bail
out for
// some address families, even if
"AddressFamilySupported"
@@ -147,6 +150,7 @@
this.localEP = null;
this.remoteEP = remoteEP;
this.readLock = new Object();
+ this.blockingOps = new BlockingOperations();
}
// Destructor.
@@ -213,11 +217,14 @@
// Accept a new connection on the socket. We
do this outside
// of the lock's protection so that multiple
threads can
// wait for incoming connections on the same
socket.
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
if(!SocketMethods.Accept
(currentHandle, addrReturn, out
newHandle))
{
throw new
SocketException(this.GetErrno());
}
+ }
// Create the end-point object for the remote
side.
remoteEP = LocalEndPoint.Create(new
SocketAddress(addrReturn));
@@ -743,10 +750,13 @@
}
// Connect to the foreign location.
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
if(!SocketMethods.Connect(handle, addr))
{
throw new
SocketException(this.GetErrno());
}
+ }
connected = true;
this.remoteEP = remoteEP;
}
@@ -761,6 +771,7 @@
{
SocketMethods.Close(handle);
handle = InvalidHandle;
+ blockingOps.Abort();
}
}
}
@@ -939,11 +950,15 @@
throw new
SocketException(Errno.EINVAL);
}
byte[] data = new byte
[optionLength];
-
if(!SocketMethods.DiscoverIrDADevices(handle, data))
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
+
if(!SocketMethods.DiscoverIrDADevices
+
(handle, data))
{
throw new
SocketException
(this.GetErrno());
}
+ }
return data;
}
}
@@ -995,6 +1010,8 @@
array[0] = GetHandle(this);
// Perform the select.
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
switch(mode)
{
case SelectMode.SelectRead:
@@ -1025,6 +1042,7 @@
}
// Not reached.
}
+ }
// Decode the result and return.
if(result == 0)
@@ -1058,8 +1076,11 @@
throw new
ObjectDisposedException
(S._("Exception_Disposed"));
}
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
result = SocketMethods.Receive
(handle, buffer, offset, size,
(int)socketFlags);
+ }
if(result < 0)
{
throw new
SocketException(this.GetErrno());
@@ -1121,9 +1142,12 @@
throw new
ObjectDisposedException
(S._("Exception_Disposed"));
}
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
result = SocketMethods.ReceiveFrom
(handle, buffer, offset, size,
(int)socketFlags, addrReturn);
+ }
if(result < 0)
{
throw new
SocketException(this.GetErrno());
@@ -1380,8 +1404,11 @@
throw new
ObjectDisposedException
(S._("Exception_Disposed"));
}
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
result = SocketMethods.Send
(handle, buffer, offset, size,
(int)socketFlags);
+ }
if(result < 0)
{
throw new
SocketException(this.GetErrno());
@@ -1442,8 +1469,12 @@
throw new
ObjectDisposedException
(S._("Exception_Disposed"));
}
+ using(BlockingOperation op =
blockingOps.NewOp())
+ {
result = SocketMethods.SendTo
- (handle, buffer, offset, size,
(int)socketFlags, addr);
+ (handle, buffer,
offset, size,
+ (int)socketFlags,
addr);
+ }
if(result < 0)
{
throw new
SocketException(this.GetErrno());
Index: DotGNU.Misc/BlockingOperation.cs
===================================================================
RCS file: DotGNU.Misc/BlockingOperation.cs
diff -N DotGNU.Misc/BlockingOperation.cs
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DotGNU.Misc/BlockingOperation.cs 12 Oct 2007 15:10:55 -0000 1.1
@@ -0,0 +1,37 @@
+/*
+ * BlockingOperation.cs - Class for aborting blocking operation.
+ *
+ * Copyright (C) 2007 Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+namespace DotGNU.Misc
+{
+
+using System;
+using System.Threading;
+using System.Runtime.CompilerServices;
+
+public sealed class BlockingOperation
+{
+ // Send IL_SIG_ABORT to given thread to cancel operation that is
blocking
+ // in system call.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ extern public static void ThreadSigAbort(Thread thread);
+
+}; // class BlockingOperation
+
+}; // namespace DotGNU.Misc
Index: System/Private/BlockingOperation.cs
===================================================================
RCS file: System/Private/BlockingOperation.cs
diff -N System/Private/BlockingOperation.cs
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ System/Private/BlockingOperation.cs 12 Oct 2007 15:10:55 -0000 1.1
@@ -0,0 +1,84 @@
+/*
+ * BlockingOperation.cs - Helper class for aborting blocking operation.
+ *
+ * Copyright (C) 2007 Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+namespace System.Private
+{
+
+using System;
+using System.Threading;
+using System.Runtime.CompilerServices;
+
+// Helper that must be disposed after blocking operation ends.
+internal sealed class BlockingOperation : IDisposable
+{
+ // Internal state.
+ private Thread thread;
+ private BlockingOperation next;
+
+ // Constructor.
+ public BlockingOperation(Thread thread)
+ {
+ this.thread = thread;
+ }
+
+ public Thread Thread
+ {
+ get
+ {
+ return thread;
+ }
+ set
+ {
+ thread = value;
+ }
+ }
+
+ public BlockingOperation Next
+ {
+ get
+ {
+ return next;
+ }
+ set
+ {
+ next = value;
+ }
+ }
+
+ // Send IL_SIG_ABORT to given thread to cancel operation that is
blocking
+ // in system call.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ extern public static void ThreadSigAbort(Thread thread);
+
+ // Handle leave from blocking operation.
+ public void Dispose()
+ {
+ thread = null;
+ }
+
+ public void Abort()
+ {
+ ThreadSigAbort(thread);
+ thread = null;
+ }
+
+}; // class BlockingOperation
+
+}; // namespace System.Private
Index: System/Private/BlockingOperations.cs
===================================================================
RCS file: System/Private/BlockingOperations.cs
diff -N System/Private/BlockingOperations.cs
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ System/Private/BlockingOperations.cs 12 Oct 2007 15:10:55 -0000
1.1
@@ -0,0 +1,104 @@
+/*
+ * BlockingOperations.cs - Class used to abort blocking operations on unixes.
+ *
+ * Copyright (C) 2007 Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+namespace System.Private
+{
+
+using System;
+using System.Threading;
+using Platform;
+
+// On unix when thread enters blocking system call (e.g. socket accept), it
+// cant be regulary aborted from managed code. On windows you can unblock the
+// thread by closing socket's handle.
+//
+// This class is used to emulate the windows behavior by sending abort signal
+// when socket is closed.
+//
+// This class holds references to threads that are blocked in kernel calls.
+// Call NewOp() before you start blocking operation and dispose returned result
+// when blocking operation ends. For example:
+//
+// using(BlockingOperation op = blockingOps.NewOp())
+// {
+// some_blocking_operation_e_g_socket.accept();
+// }
+//
+// After you close resource of blocking operation (socket), you can call
+// Abort() to unblock all registered operations that are blocking.
+internal sealed class BlockingOperations
+{
+ // Internal state.
+ private BlockingOperation operations;
+
+ // Constructor.
+ public BlockingOperations()
+ {
+ }
+
+ // Call this method before starting blocking operation.
+ // Dispose result after operation is done.
+ public BlockingOperation NewOp()
+ {
+ lock(this)
+ {
+ // Try to find free handler
+ BlockingOperation o = operations;
+ while(o != null)
+ {
+ if(o.Thread == null)
+ {
+ o.Thread =
Thread.CurrentThread;
+ return o;
+ }
+ else
+ {
+ o = o.Next;
+ }
+ }
+
+ // Create new handler and append other
handlers
+ o = operations;
+ operations = new
BlockingOperation(Thread.CurrentThread);
+ operations.Next = o;
+ return operations;
+ }
+ }
+
+ // Abort all blocking operations.
+ public void Abort()
+ {
+ lock(this)
+ {
+ BlockingOperation o = operations;
+ while(o != null)
+ {
+ if(o.Thread != null)
+ {
+ o.Abort();
+ }
+ o = o.Next;
+ }
+ }
+ }
+
+}; // class BlockingOperations
+
+}; // namespace System.Private
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [dotgnu-pnet-commits] pnetlib ChangeLog System/Net/Sockets/Socket.cs ...,
Radek Polak <=