Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGonzalo Paniagua Javier <gonzalo.mono@gmail.com>2004-01-24 16:07:14 +0300
committerGonzalo Paniagua Javier <gonzalo.mono@gmail.com>2004-01-24 16:07:14 +0300
commit8fc4e8ba06e1c9cda2b92b08aa59980e5e7563d7 (patch)
tree1667220f4c76829508420782cf8eb282e2199471 /mcs/class/System/System.Net.Sockets
parent085a64e6bf88f98bce24b1a6c9b38511e4a44e09 (diff)
2004-01-24 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* Socket.cs: if we have a pending async event, delay socket closing until EndX is called. Fixes bug #53229. Check parameters and if the socket has been disposed. Implemented IDisposable explicitly. The threads created have IsBackground = true now. svn path=/trunk/mcs/; revision=22464
Diffstat (limited to 'mcs/class/System/System.Net.Sockets')
-rw-r--r--mcs/class/System/System.Net.Sockets/ChangeLog7
-rw-r--r--mcs/class/System/System.Net.Sockets/Socket.cs212
2 files changed, 203 insertions, 16 deletions
diff --git a/mcs/class/System/System.Net.Sockets/ChangeLog b/mcs/class/System/System.Net.Sockets/ChangeLog
index 2d01884ac02..4f537c917a1 100644
--- a/mcs/class/System/System.Net.Sockets/ChangeLog
+++ b/mcs/class/System/System.Net.Sockets/ChangeLog
@@ -1,3 +1,10 @@
+2004-01-24 Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+ * Socket.cs: if we have a pending async event, delay socket closing
+ until EndX is called. Fixes bug #53229. Check parameters and if the
+ socket has been disposed. Implemented IDisposable explicitly. The
+ threads created have IsBackground = true now.
+
2004-01-10 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* Socket.cs: patch from Brad Fitzpatrick <brad@danga.com> episode 2.
diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs b/mcs/class/System/System.Net.Sockets/Socket.cs
index 4e7502aeb87..c5b08928ade 100644
--- a/mcs/class/System/System.Net.Sockets/Socket.cs
+++ b/mcs/class/System/System.Net.Sockets/Socket.cs
@@ -298,6 +298,8 @@ namespace System.Net.Sockets
private SocketType socket_type;
private ProtocolType protocol_type;
private bool blocking=true;
+ private int pendingEnds;
+ private int closeDelayed;
/*
* These two fields are looked up by name by the runtime, don't change
@@ -309,6 +311,8 @@ namespace System.Net.Sockets
* the last IO operation
*/
private bool connected=false;
+ /* true if we called Close_internal */
+ private bool closed;
/* Used in LocalEndPoint and RemoteEndPoint if the
* Mono.Posix assembly is available
@@ -468,6 +472,9 @@ namespace System.Net.Sockets
public int Available {
get {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
return(Available_internal(socket));
}
}
@@ -505,6 +512,9 @@ namespace System.Net.Sockets
[MonoTODO("Support non-IP endpoints")]
public EndPoint LocalEndPoint {
get {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
SocketAddress sa;
sa=LocalEndPoint_internal(socket);
@@ -535,6 +545,9 @@ namespace System.Net.Sockets
[MonoTODO("Support non-IP endpoints")]
public EndPoint RemoteEndPoint {
get {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
SocketAddress sa;
sa=RemoteEndPoint_internal(socket);
@@ -627,6 +640,9 @@ namespace System.Net.Sockets
private extern static IntPtr Accept_internal(IntPtr sock);
public Socket Accept() {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
IntPtr sock=Accept_internal(socket);
return(new Socket(this.AddressFamily, this.SocketType,
@@ -635,10 +651,16 @@ namespace System.Net.Sockets
public IAsyncResult BeginAccept(AsyncCallback callback,
object state) {
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ Interlocked.Increment (ref pendingEnds);
SocketAsyncResult req=new SocketAsyncResult(state);
Worker worker=new Worker(this, callback, req);
req.Worker=worker;
Thread child=new Thread(new ThreadStart(worker.Accept));
+ child.IsBackground = true;
child.Start();
return(req);
}
@@ -646,11 +668,20 @@ namespace System.Net.Sockets
public IAsyncResult BeginConnect(EndPoint end_point,
AsyncCallback callback,
object state) {
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (end_point == null)
+ throw new ArgumentNullException ("end_point");
+
+ Interlocked.Increment (ref pendingEnds);
SocketAsyncResult req=new SocketAsyncResult(state);
Worker worker=new Worker(this, end_point, callback,
req);
req.Worker=worker;
Thread child=new Thread(new ThreadStart(worker.Connect));
+ child.IsBackground = true;
child.Start();
return(req);
}
@@ -660,11 +691,29 @@ namespace System.Net.Sockets
SocketFlags socket_flags,
AsyncCallback callback,
object state) {
+
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+ if (size < 0)
+ throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+ if (offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+ Interlocked.Increment (ref pendingEnds);
SocketAsyncResult req=new SocketAsyncResult(state);
Worker worker=new Worker(this, buffer, offset, size,
socket_flags, callback, req);
req.Worker=worker;
Thread child=new Thread(new ThreadStart(worker.Receive));
+ child.IsBackground = true;
child.Start();
return(req);
}
@@ -675,12 +724,29 @@ namespace System.Net.Sockets
ref EndPoint remote_end,
AsyncCallback callback,
object state) {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+ if (size < 0)
+ throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+ if (offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+ Interlocked.Increment (ref pendingEnds);
SocketAsyncResult req=new SocketAsyncResult(state);
Worker worker=new Worker(this, buffer, offset, size,
socket_flags, remote_end,
callback, req);
req.Worker=worker;
Thread child=new Thread(new ThreadStart(worker.ReceiveFrom));
+ child.IsBackground = true;
child.Start();
return(req);
}
@@ -690,11 +756,28 @@ namespace System.Net.Sockets
SocketFlags socket_flags,
AsyncCallback callback,
object state) {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+ if (size < 0)
+ throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+ if (offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+ Interlocked.Increment (ref pendingEnds);
SocketAsyncResult req=new SocketAsyncResult(state);
Worker worker=new Worker(this, buffer, offset, size,
socket_flags, callback, req);
req.Worker=worker;
Thread child=new Thread(new ThreadStart(worker.Send));
+ child.IsBackground = true;
child.Start();
return(req);
}
@@ -705,12 +788,29 @@ namespace System.Net.Sockets
EndPoint remote_end,
AsyncCallback callback,
object state) {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (buffer == null)
+ throw new ArgumentNullException ("buffer");
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException ("offset must be >= 0");
+
+ if (size < 0)
+ throw new ArgumentOutOfRangeException ("size must be >= 0");
+
+ if (offset + size > buffer.Length)
+ throw new ArgumentOutOfRangeException ("offset + size exceeds the buffer length");
+
+ Interlocked.Increment (ref pendingEnds);
SocketAsyncResult req=new SocketAsyncResult(state);
Worker worker=new Worker(this, buffer, offset, size,
socket_flags, remote_end,
callback, req);
req.Worker=worker;
Thread child=new Thread(new ThreadStart(worker.SendTo));
+ child.IsBackground = true;
child.Start();
return(req);
}
@@ -721,8 +821,11 @@ namespace System.Net.Sockets
SocketAddress sa);
public void Bind(EndPoint local_end) {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
if(local_end==null) {
- throw new ArgumentNullException();
+ throw new ArgumentNullException("local_end");
}
Bind_internal(socket, local_end.Serialize());
@@ -733,7 +836,7 @@ namespace System.Net.Sockets
private extern static void Close_internal(IntPtr socket);
public void Close() {
- this.Dispose();
+ ((IDisposable) this).Dispose ();
}
// Connects to the remote address
@@ -742,8 +845,11 @@ namespace System.Net.Sockets
SocketAddress sa);
public void Connect(EndPoint remote_end) {
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
if(remote_end==null) {
- throw new ArgumentNullException();
+ throw new ArgumentNullException("remote_end");
}
Connect_internal(socket, remote_end.Serialize());
@@ -751,54 +857,122 @@ namespace System.Net.Sockets
}
public Socket EndAccept(IAsyncResult result) {
- SocketAsyncResult req=(SocketAsyncResult)result;
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ SocketAsyncResult req = result as SocketAsyncResult;
+ if (req == null)
+ throw new ArgumentException ("Invalid IAsyncResult");
result.AsyncWaitHandle.WaitOne();
+ Interlocked.Decrement (ref pendingEnds);
+ CheckIfClose ();
req.CheckIfThrowDelayedException();
return(req.Worker.Socket);
}
public void EndConnect(IAsyncResult result) {
- SocketAsyncResult req=(SocketAsyncResult)result;
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ SocketAsyncResult req = result as SocketAsyncResult;
+ if (req == null)
+ throw new ArgumentException ("Invalid IAsyncResult");
result.AsyncWaitHandle.WaitOne();
+ Interlocked.Decrement (ref pendingEnds);
+ CheckIfClose ();
req.CheckIfThrowDelayedException();
}
public int EndReceive(IAsyncResult result) {
- SocketAsyncResult req=(SocketAsyncResult)result;
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ SocketAsyncResult req = result as SocketAsyncResult;
+ if (req == null)
+ throw new ArgumentException ("Invalid IAsyncResult");
result.AsyncWaitHandle.WaitOne();
+ Interlocked.Decrement (ref pendingEnds);
+ CheckIfClose ();
req.CheckIfThrowDelayedException();
return(req.Worker.Total);
}
public int EndReceiveFrom(IAsyncResult result,
ref EndPoint end_point) {
- SocketAsyncResult req=(SocketAsyncResult)result;
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ SocketAsyncResult req = result as SocketAsyncResult;
+ if (req == null)
+ throw new ArgumentException ("Invalid IAsyncResult");
result.AsyncWaitHandle.WaitOne();
+ Interlocked.Decrement (ref pendingEnds);
+ CheckIfClose ();
req.CheckIfThrowDelayedException();
end_point=req.Worker.EndPoint;
return(req.Worker.Total);
}
public int EndSend(IAsyncResult result) {
- SocketAsyncResult req=(SocketAsyncResult)result;
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ SocketAsyncResult req = result as SocketAsyncResult;
+ if (req == null)
+ throw new ArgumentException ("Invalid IAsyncResult");
result.AsyncWaitHandle.WaitOne();
+ Interlocked.Decrement (ref pendingEnds);
+ CheckIfClose ();
req.CheckIfThrowDelayedException();
return(req.Worker.Total);
}
public int EndSendTo(IAsyncResult result) {
- SocketAsyncResult req=(SocketAsyncResult)result;
+ if (disposed && closed)
+ throw new ObjectDisposedException (GetType ().ToString ());
+
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ SocketAsyncResult req = result as SocketAsyncResult;
+ if (req == null)
+ throw new ArgumentException ("Invalid IAsyncResult");
result.AsyncWaitHandle.WaitOne();
+ Interlocked.Decrement (ref pendingEnds);
+ CheckIfClose ();
req.CheckIfThrowDelayedException();
return(req.Worker.Total);
}
+ void CheckIfClose ()
+ {
+ if (Interlocked.CompareExchange (ref closeDelayed, 1, 0) == 1) {
+ closed = true;
+ Close_internal(socket);
+ }
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -1148,7 +1322,7 @@ namespace System.Net.Sockets
return (int) socket;
}
- private bool disposed = false;
+ private bool disposed;
protected virtual void Dispose(bool explicitDisposing) {
// Check to see if Dispose has already been called
@@ -1163,16 +1337,22 @@ namespace System.Net.Sockets
this.disposed=true;
connected=false;
- Close_internal(socket);
+ Interlocked.CompareExchange (ref closeDelayed, 0, 1);
+ if (Interlocked.CompareExchange (ref pendingEnds, 0, 0) == 0) {
+ if (Interlocked.CompareExchange (ref closeDelayed, 1, 0) == 1) {
+ closed = true;
+ Close_internal(socket);
+ }
+ }
}
}
- public void Dispose() {
- Dispose(true);
- // Take yourself off the Finalization queue
- GC.SuppressFinalize(this);
+ void IDisposable.Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
}
-
+
~Socket () {
Dispose(false);
}