Browse Source

[w32handle] Remove use of w32handle for File, Console, Pipe and Socket (#5319)

* [w32file] Remove io_ops indirection

* [w32file] Replace use of w32handle by a GHashTable for File, Console and Pipe

* [Socket] Avoid relying on MonoIO.DuplicateHandle

* [w32socket] Remove force closing of sockets on shutdown

* fixup! [Socket] Avoid relying on MonoIO.DuplicateHandle

* [w32socket] Replace use of w32handle by a GHashTable

* [w32handle] Remove dead function mono_w32handle_new_fd

* fixup! [w32file] Replace use of w32handle by a GHashTable for File, Console and Pipe

* [w32handle] Remove dead variable mono_w32handle_fd_reserve

* [fdhandle] Factor w32file and w32socket common fdhandle code

* fixup! [Socket] Avoid relying on MonoIO.DuplicateHandle

* [w32socket] Fix GC safe/unsafe transitions

* fixup! [w32handle] Remove dead variable mono_w32handle_fd_reserve
Ludovic Henry 8 years ago
parent
commit
bf3ac1d7fc

+ 4 - 2
mcs/class/System/System.Net.Sockets/Socket.cs

@@ -2265,6 +2265,9 @@ m_Handle, buffer, offset + sent, size - sent, socketFlags, out nativeError, is_b
 
 #region DuplicateAndClose
 
+		[MethodImplAttribute(MethodImplOptions.InternalCall)]
+		static extern bool Duplicate_internal(IntPtr handle, int targetProcessId, out IntPtr duplicateHandle, out MonoIOError error);
+
 		[MonoLimitation ("We do not support passing sockets across processes, we merely allow this API to pass the socket across AppDomains")]
 		public SocketInformation DuplicateAndClose (int targetProcessId)
 		{
@@ -2275,9 +2278,8 @@ m_Handle, buffer, offset + sent, size - sent, socketFlags, out nativeError, is_b
 				(is_blocking       ? 0 : SocketInformationOptions.NonBlocking) |
 				(useOverlappedIO ? SocketInformationOptions.UseOnlyOverlappedIO : 0);
 
-			MonoIOError error;
 			IntPtr duplicateHandle;
-			if (!MonoIO.DuplicateHandle (System.Diagnostics.Process.GetCurrentProcess ().Handle, Handle, new IntPtr (targetProcessId), out duplicateHandle, 0, 0, 0x00000002 /* DUPLICATE_SAME_ACCESS */, out error))
+			if (!Duplicate_internal (Handle, targetProcessId, out duplicateHandle, out MonoIOError error))
 				throw MonoIO.GetException (error);
 
 			si.ProtocolInformation = Mono.DataConverter.Pack ("iiiil", (int)addressFamily, (int)socketType, (int)protocolType, is_bound ? 1 : 0, (long)duplicateHandle);

+ 3 - 1
mono/metadata/Makefile.am

@@ -281,7 +281,9 @@ common_sources = \
 	sre.c	\
 	sre-encode.c	\
 	sre-save.c	\
-	custom-attrs.c
+	custom-attrs.c	\
+	fdhandle.h	\
+	fdhandle.c
 
 # These source files have compile time dependencies on GC code
 gc_dependent_sources = \

+ 142 - 0
mono/metadata/fdhandle.c

@@ -0,0 +1,142 @@
+
+#include "fdhandle.h"
+#include "utils/mono-lazy-init.h"
+#include "utils/mono-coop-mutex.h"
+
+static GHashTable *fds;
+static MonoCoopMutex fds_mutex;
+static MonoFDHandleCallback fds_callback[MONO_FDTYPE_COUNT];
+static mono_lazy_init_t fds_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+
+static const gchar *types_str[] = {
+	"File",
+	"Console",
+	"Pipe",
+	"Socket",
+	NULL
+};
+
+static void
+fds_remove (gpointer data)
+{
+	MonoFDHandle* fdhandle;
+
+	fdhandle = (MonoFDHandle*) data;
+	g_assert (fdhandle);
+
+	g_assert (fds_callback [fdhandle->type].close);
+	fds_callback [fdhandle->type].close (fdhandle);
+
+	mono_refcount_dec (fdhandle);
+}
+
+static void
+initialize (void)
+{
+	fds = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, fds_remove);
+	mono_coop_mutex_init (&fds_mutex);
+}
+
+void
+mono_fdhandle_register (MonoFDType type, MonoFDHandleCallback *callback)
+{
+	mono_lazy_initialize (&fds_init, initialize);
+	memcpy (&fds_callback [type], callback, sizeof (MonoFDHandleCallback));
+}
+
+static void
+fdhandle_destroy (gpointer data)
+{
+	MonoFDHandle* fdhandle;
+
+	fdhandle = (MonoFDHandle*) data;
+	g_assert (fdhandle);
+
+	g_assert (fds_callback [fdhandle->type].destroy);
+	fds_callback [fdhandle->type].destroy (fdhandle);
+}
+
+void
+mono_fdhandle_init (MonoFDHandle *fdhandle, MonoFDType type, gint fd)
+{
+	mono_refcount_init (fdhandle, fdhandle_destroy);
+	fdhandle->type = type;
+	fdhandle->fd = fd;
+}
+
+void
+mono_fdhandle_insert (MonoFDHandle *fdhandle)
+{
+	mono_coop_mutex_lock (&fds_mutex);
+
+	if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL))
+		g_error("%s: duplicate %s fd %d", __func__, types_str [fdhandle->type], fdhandle->fd);
+
+	g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
+
+	mono_coop_mutex_unlock (&fds_mutex);
+}
+
+gboolean
+mono_fdhandle_try_insert (MonoFDHandle *fdhandle)
+{
+	mono_coop_mutex_lock (&fds_mutex);
+
+	if (g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fdhandle->fd), NULL, NULL)) {
+		/* we raced between 2 invocations of mono_fdhandle_try_insert */
+		mono_coop_mutex_unlock (&fds_mutex);
+
+		return FALSE;
+	}
+
+	g_hash_table_insert (fds, GINT_TO_POINTER(fdhandle->fd), fdhandle);
+
+	mono_coop_mutex_unlock (&fds_mutex);
+
+	return TRUE;
+}
+
+gboolean
+mono_fdhandle_lookup_and_ref (gint fd, MonoFDHandle **fdhandle)
+{
+	mono_coop_mutex_lock (&fds_mutex);
+
+	if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) fdhandle)) {
+		mono_coop_mutex_unlock (&fds_mutex);
+		return FALSE;
+	}
+
+	mono_refcount_inc (*fdhandle);
+
+	mono_coop_mutex_unlock (&fds_mutex);
+
+	return TRUE;
+}
+
+void
+mono_fdhandle_unref (MonoFDHandle *fdhandle)
+{
+	mono_refcount_dec (fdhandle);
+}
+
+gboolean
+mono_fdhandle_close (gint fd)
+{
+	MonoFDHandle *fdhandle;
+	gboolean removed;
+
+	mono_coop_mutex_lock (&fds_mutex);
+
+	if (!g_hash_table_lookup_extended (fds, GINT_TO_POINTER(fd), NULL, (gpointer*) &fdhandle)) {
+		mono_coop_mutex_unlock (&fds_mutex);
+
+		return FALSE;
+	}
+
+	removed = g_hash_table_remove (fds, GINT_TO_POINTER(fdhandle->fd));
+	g_assert (removed);
+
+	mono_coop_mutex_unlock (&fds_mutex);
+
+	return TRUE;
+}

+ 50 - 0
mono/metadata/fdhandle.h

@@ -0,0 +1,50 @@
+
+#ifndef __MONO_METADATA_FDHANDLE_H__
+#define __MONO_METADATA_FDHANDLE_H__
+
+#include <config.h>
+#include <glib.h>
+
+#include "utils/refcount.h"
+
+typedef enum {
+	MONO_FDTYPE_FILE,
+	MONO_FDTYPE_CONSOLE,
+	MONO_FDTYPE_PIPE,
+	MONO_FDTYPE_SOCKET,
+	MONO_FDTYPE_COUNT
+} MonoFDType;
+
+typedef struct {
+	MonoRefCount ref;
+	MonoFDType type;
+	gint fd;
+} MonoFDHandle;
+
+typedef struct {
+	void (*close) (MonoFDHandle *fdhandle);
+	void (*destroy) (MonoFDHandle *fdhandle);
+} MonoFDHandleCallback;
+
+void
+mono_fdhandle_register (MonoFDType type, MonoFDHandleCallback *callback);
+
+void
+mono_fdhandle_init (MonoFDHandle *fdhandle, MonoFDType type, gint fd);
+
+void
+mono_fdhandle_insert (MonoFDHandle *fdhandle);
+
+gboolean
+mono_fdhandle_try_insert (MonoFDHandle *fdhandle);
+
+gboolean
+mono_fdhandle_lookup_and_ref (gint fd, MonoFDHandle **fdhandle);
+
+void
+mono_fdhandle_unref (MonoFDHandle *fdhandle);
+
+gboolean
+mono_fdhandle_close (gint fd);
+
+#endif /* __MONO_METADATA_FDHANDLE_H__ */

+ 2 - 1
mono/metadata/icall-def.h

@@ -459,7 +459,8 @@ HANDLES(ICALL(SOCK_3, "Bind_internal(intptr,System.Net.SocketAddress,int&)", ves
 HANDLES(ICALL(SOCK_4, "Blocking_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Blocking_internal))
 HANDLES(ICALL(SOCK_5, "Close_internal(intptr,int&)", ves_icall_System_Net_Sockets_Socket_Close_internal))
 HANDLES(ICALL(SOCK_6, "Connect_internal(intptr,System.Net.SocketAddress,int&,bool)", ves_icall_System_Net_Sockets_Socket_Connect_internal))
-HANDLES(ICALL (SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal))
+HANDLES(ICALL(SOCK_6a, "Disconnect_internal(intptr,bool,int&)", ves_icall_System_Net_Sockets_Socket_Disconnect_internal))
+HANDLES(ICALL(SOCK_6b, "Duplicate_internal", ves_icall_System_Net_Sockets_Socket_Duplicate_internal))
 HANDLES(ICALL(SOCK_7, "GetSocketOption_arr_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,byte[]&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal))
 HANDLES(ICALL(SOCK_8, "GetSocketOption_obj_internal(intptr,System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,object&,int&)", ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal))
 HANDLES(ICALL(SOCK_21, "IOControl_internal(intptr,int,byte[],byte[],int&)", ves_icall_System_Net_Sockets_Socket_IOControl_internal))

File diff suppressed because it is too large
+ 153 - 476
mono/metadata/w32file-unix.c


+ 7 - 9
mono/metadata/w32file.c

@@ -1065,24 +1065,22 @@ MonoBoolean
 ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
 		HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
 {
-	/* This is only used on Windows */
+#ifndef HOST_WIN32
+	*target_handle = mono_w32handle_duplicate (source_handle);
+#else
 	gboolean ret;
-	
-#ifdef HOST_WIN32
+
 	MONO_ENTER_GC_SAFE;
 	ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
 	MONO_EXIT_GC_SAFE;
-#else
-	*target_handle = mono_w32handle_duplicate (source_handle);
-	ret = TRUE;
-#endif
 
-	if(ret==FALSE) {
+	if (!ret) {
 		*error = mono_w32error_get_last ();
 		/* FIXME: throw an exception? */
 		return(FALSE);
 	}
-	
+#endif
+
 	return(TRUE);
 }
 

+ 31 - 160
mono/metadata/w32handle.c

@@ -51,10 +51,7 @@ static MonoW32HandleOps *handle_ops [MONO_W32HANDLE_COUNT];
 #define SLOT_OFFSET(x)	(x % HANDLE_PER_SLOT)
 
 static MonoW32HandleBase *private_handles [SLOT_MAX];
-static guint32 private_handles_count = 0;
-static guint32 private_handles_slots_count = 0;
-
-guint32 mono_w32handle_fd_reserve;
+static guint32 private_handles_size = 0;
 
 /*
  * This is an internal handle which is used for handling waiting for multiple handles.
@@ -68,20 +65,6 @@ static mono_mutex_t scan_mutex;
 
 static gboolean shutting_down = FALSE;
 
-static gboolean
-type_is_fd (MonoW32HandleType type)
-{
-	switch (type) {
-	case MONO_W32HANDLE_FILE:
-	case MONO_W32HANDLE_CONSOLE:
-	case MONO_W32HANDLE_SOCKET:
-	case MONO_W32HANDLE_PIPE:
-		return TRUE;
-	default:
-		return FALSE;
-	}
-}
-
 static gboolean
 mono_w32handle_lookup_data (gpointer handle, MonoW32HandleBase **handle_data)
 {
@@ -279,19 +262,6 @@ mono_w32handle_init (void)
 	g_assert ((sizeof (handle_ops) / sizeof (handle_ops[0]))
 		  == MONO_W32HANDLE_COUNT);
 
-	/* This is needed by the code in mono_w32handle_new_internal */
-	mono_w32handle_fd_reserve = (eg_getdtablesize () + (HANDLE_PER_SLOT - 1)) & ~(HANDLE_PER_SLOT - 1);
-
-	do {
-		/*
-		 * The entries in private_handles reserved for fds are allocated lazily to
-		 * save memory.
-		 */
-
-		private_handles_count += HANDLE_PER_SLOT;
-		private_handles_slots_count ++;
-	} while(mono_w32handle_fd_reserve > private_handles_count);
-
 	mono_os_mutex_init (&scan_mutex);
 
 	mono_os_cond_init (&global_signal_cond);
@@ -315,22 +285,6 @@ mono_w32handle_cleanup (void)
 static gsize
 mono_w32handle_ops_typesize (MonoW32HandleType type);
 
-static void mono_w32handle_init_handle (MonoW32HandleBase *handle,
-			       MonoW32HandleType type, gpointer handle_specific)
-{
-	g_assert (handle->ref == 0);
-
-	handle->type = type;
-	handle->signalled = FALSE;
-	handle->ref = 1;
-
-	mono_os_cond_init (&handle->signal_cond);
-	mono_os_mutex_init (&handle->signal_mutex);
-
-	if (handle_specific)
-		handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type));
-}
-
 /*
  * mono_w32handle_new_internal:
  * @type: Init handle to this type
@@ -352,15 +306,16 @@ static guint32 mono_w32handle_new_internal (MonoW32HandleType type,
 	 * descriptors
 	 */
 
-	if (last < mono_w32handle_fd_reserve) {
-		last = mono_w32handle_fd_reserve;
+	if (last == 0) {
+		/* We need to go from 1 since a handle of value 0 can be considered invalid in managed code */
+		last = 1;
 	} else {
 		retry = TRUE;
 	}
 
 again:
 	count = last;
-	for(i = SLOT_INDEX (count); i < private_handles_slots_count; i++) {
+	for(i = SLOT_INDEX (count); i < private_handles_size; i++) {
 		if (private_handles [i]) {
 			for (k = SLOT_OFFSET (count); k < HANDLE_PER_SLOT; k++) {
 				MonoW32HandleBase *handle = &private_handles [i][k];
@@ -368,7 +323,18 @@ again:
 				if(handle->type == MONO_W32HANDLE_UNUSED) {
 					last = count + 1;
 
-					mono_w32handle_init_handle (handle, type, handle_specific);
+					g_assert (handle->ref == 0);
+
+					handle->type = type;
+					handle->signalled = FALSE;
+					handle->ref = 1;
+
+					mono_os_cond_init (&handle->signal_cond);
+					mono_os_mutex_init (&handle->signal_mutex);
+
+					if (handle_specific)
+						handle->specific = g_memdup (handle_specific, mono_w32handle_ops_typesize (type));
+
 					return (count);
 				}
 				count++;
@@ -376,108 +342,50 @@ again:
 		}
 	}
 
-	if(retry && last > mono_w32handle_fd_reserve) {
+	if (retry) {
 		/* Try again from the beginning */
-		last = mono_w32handle_fd_reserve;
+		last = 1;
+		retry = FALSE;
 		goto again;
 	}
 
 	/* Will need to expand the array.  The caller will sort it out */
 
-	return(0);
+	return G_MAXUINT32;
 }
 
 gpointer
 mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific)
 {
-	guint32 handle_idx = 0;
+	guint32 handle_idx;
 	gpointer handle;
 
 	g_assert (!shutting_down);
 
-	g_assert(!type_is_fd(type));
-
 	mono_os_mutex_lock (&scan_mutex);
 
-	while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == 0) {
+	while ((handle_idx = mono_w32handle_new_internal (type, handle_specific)) == G_MAXUINT32) {
 		/* Try and expand the array, and have another go */
-		int idx = SLOT_INDEX (private_handles_count);
-		if (idx >= SLOT_MAX) {
-			break;
-		}
+		if (private_handles_size >= SLOT_MAX) {
+			mono_os_mutex_unlock (&scan_mutex);
 
-		private_handles [idx] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
+			/* We ran out of slots */
+			mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type));
+			return INVALID_HANDLE_VALUE;
+		}
 
-		private_handles_count += HANDLE_PER_SLOT;
-		private_handles_slots_count ++;
+		private_handles [private_handles_size ++] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
 	}
 
 	mono_os_mutex_unlock (&scan_mutex);
 
-	if (handle_idx == 0) {
-		/* We ran out of slots */
-		handle = INVALID_HANDLE_VALUE;
-		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle", __func__, mono_w32handle_ops_typename (type));
-		goto done;
-	}
-
-	/* Make sure we left the space for fd mappings */
-	g_assert (handle_idx >= mono_w32handle_fd_reserve);
-
 	handle = GUINT_TO_POINTER (handle_idx);
 
 	mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
 
-done:
 	return(handle);
 }
 
-gpointer mono_w32handle_new_fd (MonoW32HandleType type, int fd,
-			      gpointer handle_specific)
-{
-	MonoW32HandleBase *handle_data;
-	int fd_index, fd_offset;
-
-	g_assert (!shutting_down);
-
-	g_assert(type_is_fd(type));
-
-	if (fd >= mono_w32handle_fd_reserve) {
-		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is too big", __func__, mono_w32handle_ops_typename (type));
-
-		return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
-	}
-
-	fd_index = SLOT_INDEX (fd);
-	fd_offset = SLOT_OFFSET (fd);
-
-	mono_os_mutex_lock (&scan_mutex);
-	/* Initialize the array entries on demand */
-	if (!private_handles [fd_index]) {
-		if (!private_handles [fd_index])
-			private_handles [fd_index] = g_new0 (MonoW32HandleBase, HANDLE_PER_SLOT);
-	}
-
-	handle_data = &private_handles [fd_index][fd_offset];
-
-	if (handle_data->type != MONO_W32HANDLE_UNUSED) {
-		mono_os_mutex_unlock (&scan_mutex);
-		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: failed to create %s handle, fd is already in use", __func__, mono_w32handle_ops_typename (type));
-		/* FIXME: clean up this handle?  We can't do anything
-		 * with the fd, cos thats the new one
-		 */
-		return(GUINT_TO_POINTER (INVALID_HANDLE_VALUE));
-	}
-
-	mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_W32HANDLE, "%s: create %s handle %p", __func__, mono_w32handle_ops_typename (type), GUINT_TO_POINTER(fd));
-
-	mono_w32handle_init_handle (handle_data, type, handle_specific);
-
-	mono_os_mutex_unlock (&scan_mutex);
-
-	return(GUINT_TO_POINTER(fd));
-}
-
 static gboolean
 mono_w32handle_ref_core (gpointer handle, MonoW32HandleBase *handle_data);
 
@@ -496,8 +404,6 @@ mono_w32handle_duplicate (gpointer handle)
 		return handle;
 	if (!mono_w32handle_lookup_data (handle, &handle_data))
 		return INVALID_HANDLE_VALUE;
-	if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE)
-		return handle;
 
 	if (!mono_w32handle_ref_core (handle, handle_data))
 		g_error ("%s: failed to ref handle %p", __func__, handle);
@@ -515,14 +421,6 @@ mono_w32handle_close (gpointer handle)
 		return FALSE;
 	if (!mono_w32handle_lookup_data (handle, &handle_data))
 		return FALSE;
-	if (handle == (gpointer) 0 && handle_data->type != MONO_W32HANDLE_CONSOLE) {
-		/* Problem: because we map file descriptors to the
-		 * same-numbered handle we can't tell the difference
-		 * between a bogus handle and the handle to stdin.
-		 * Assume that it's the console handle if that handle
-		 * exists... */
-		return FALSE;
-	}
 
 	destroy = mono_w32handle_unref_core (handle, handle_data);
 	if (destroy)
@@ -562,7 +460,7 @@ mono_w32handle_foreach (gboolean (*on_each)(gpointer handle, gpointer data, gpoi
 
 	mono_os_mutex_lock (&scan_mutex);
 
-	for (i = SLOT_INDEX (0); i < private_handles_slots_count; i++) {
+	for (i = SLOT_INDEX (0); i < private_handles_size; i++) {
 		if (!private_handles [i])
 			continue;
 		for (k = SLOT_OFFSET (0); k < HANDLE_PER_SLOT; k++) {
@@ -730,15 +628,6 @@ mono_w32handle_unref (gpointer handle)
 		w32handle_destroy (handle);
 }
 
-static void
-mono_w32handle_ops_close (gpointer handle, gpointer data);
-
-void
-mono_w32handle_force_close (gpointer handle, gpointer data)
-{
-	mono_w32handle_ops_close (handle, data);
-}
-
 void
 mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops)
 {
@@ -779,24 +668,6 @@ static void (*_wapi_handle_ops_get_close_func (MonoW32HandleType type))(gpointer
 	return (NULL);
 }
 
-static void
-mono_w32handle_ops_close (gpointer handle, gpointer data)
-{
-	MonoW32HandleBase *handle_data;
-	MonoW32HandleType type;
-
-	if (!mono_w32handle_lookup_data (handle, &handle_data)) {
-		return;
-	}
-
-	type = handle_data->type;
-
-	if (handle_ops[type] != NULL &&
-	    handle_ops[type]->close != NULL) {
-		handle_ops[type]->close (handle, data);
-	}
-}
-
 static void
 mono_w32handle_ops_details (MonoW32HandleType type, gpointer data)
 {

+ 0 - 13
mono/metadata/w32handle.h

@@ -24,16 +24,11 @@
 
 typedef enum {
 	MONO_W32HANDLE_UNUSED = 0,
-	MONO_W32HANDLE_FILE,
-	MONO_W32HANDLE_CONSOLE,
-	MONO_W32HANDLE_THREAD,
 	MONO_W32HANDLE_SEM,
 	MONO_W32HANDLE_MUTEX,
 	MONO_W32HANDLE_EVENT,
-	MONO_W32HANDLE_SOCKET,
 	MONO_W32HANDLE_FIND,
 	MONO_W32HANDLE_PROCESS,
-	MONO_W32HANDLE_PIPE,
 	MONO_W32HANDLE_NAMEDMUTEX,
 	MONO_W32HANDLE_NAMEDSEM,
 	MONO_W32HANDLE_NAMEDEVENT,
@@ -99,8 +94,6 @@ typedef enum {
 	MONO_W32HANDLE_CAP_SPECIAL_WAIT = 0x08,
 } MonoW32HandleCapability;
 
-extern guint32 mono_w32handle_fd_reserve;
-
 void
 mono_w32handle_init (void);
 
@@ -113,9 +106,6 @@ mono_w32handle_register_ops (MonoW32HandleType type, MonoW32HandleOps *ops);
 gpointer
 mono_w32handle_new (MonoW32HandleType type, gpointer handle_specific);
 
-gpointer
-mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
-
 gpointer
 mono_w32handle_duplicate (gpointer handle);
 
@@ -143,9 +133,6 @@ mono_w32handle_register_capabilities (MonoW32HandleType type, MonoW32HandleCapab
 gboolean
 mono_w32handle_test_capabilities (gpointer handle, MonoW32HandleCapability caps);
 
-void
-mono_w32handle_force_close (gpointer handle, gpointer data);
-
 void
 mono_w32handle_set_signal_state (gpointer handle, gboolean state, gboolean broadcast);
 

+ 1 - 1
mono/metadata/w32process-unix.c

@@ -1945,7 +1945,7 @@ process_create (const gunichar2 *appname, const gunichar2 *cmdline,
 		dup2 (err_fd, 2);
 
 		/* Close all file descriptors */
-		for (i = mono_w32handle_fd_reserve - 1; i > 2; i--)
+		for (i = eg_getdtablesize() - 1; i > 2; i--)
 			close (i);
 
 #ifdef DEBUG_ENABLED

+ 3 - 0
mono/metadata/w32socket-internals.h

@@ -148,4 +148,7 @@ mono_w32socket_get_last_error (void);
 gint32
 mono_w32socket_convert_error (gint error);
 
+gboolean
+mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle);
+
 #endif // __MONO_METADATA_W32SOCKET_INTERNALS_H__

File diff suppressed because it is too large
+ 315 - 221
mono/metadata/w32socket-unix.c


+ 70 - 13
mono/metadata/w32socket-win32.c

@@ -137,15 +137,19 @@ SOCKET mono_w32socket_accept (SOCKET s, struct sockaddr *addr, socklen_t *addrle
 {
 	MonoInternalThread *curthread = mono_thread_internal_current ();
 	SOCKET newsock = INVALID_SOCKET;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_ACCEPT_BIT, blocking, TRUE, newsock, accept, s, addr, addrlen);
+	MONO_EXIT_GC_SAFE;
 	return newsock;
 }
 
 int mono_w32socket_connect (SOCKET s, const struct sockaddr *name, int namelen, gboolean blocking)
 {
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_CONNECT_BIT, blocking, FALSE, ret, connect, s, name, namelen);
 	ret = WSAGetLastError () != 0 ? SOCKET_ERROR : 0;
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
@@ -153,42 +157,54 @@ int mono_w32socket_recv (SOCKET s, char *buf, int len, int flags, gboolean block
 {
 	MonoInternalThread *curthread = mono_thread_internal_current ();
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recv, s, buf, len, flags);
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
 int mono_w32socket_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking)
 {
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, recvfrom, s, buf, len, flags, from, fromlen);
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
 int mono_w32socket_recvbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking)
 {
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_READ_BIT, blocking, TRUE, ret, WSARecv, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
 int mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean blocking)
 {
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, send, s, buf, len, flags);
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
 int mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
 {
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, sendto, s, buf, len, flags, to, tolen);
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
 int mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking)
 {
 	int ret = SOCKET_ERROR;
+	MONO_ENTER_GC_SAFE;
 	ALERTABLE_SOCKET_CALL (FD_WRITE_BIT, blocking, FALSE, ret, WSASend, s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine);
+	MONO_EXIT_GC_SAFE;
 	return ret;
 }
 
@@ -197,12 +213,17 @@ BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE
 {
 	LOGDEBUG (g_message ("%06d - Performing %s TransmitFile () on socket %d", GetCurrentThreadId (), blocking ? "blocking" : "non-blocking", hSocket));
 
-	int error = 0;
+	int error = 0, ret;
+
+	MONO_ENTER_GC_SAFE;
+
 	if (blocking) {
 		OVERLAPPED overlapped = { 0 };
 		overlapped.hEvent = WSACreateEvent ();
-		if (overlapped.hEvent == WSA_INVALID_EVENT)
-			return FALSE;
+		if (overlapped.hEvent == WSA_INVALID_EVENT) {
+			ret = FALSE;
+			goto done;
+		}
 		if (!TransmitFile (hSocket, hFile, 0, 0, &overlapped, lpTransmitBuffers, dwReserved)) {
 			error = WSAGetLastError ();
 			if (error == WSA_IO_PENDING) {
@@ -230,7 +251,11 @@ BOOL mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE
 		blocking ? "blocking" : "non-blocking", hSocket, error == 0, error));
 	WSASetLastError (error);
 
-	return error == 0;
+	ret = error == 0;
+
+done:
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 #endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
@@ -243,6 +268,8 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
 	DWORD output_bytes;
 	gint ret;
 
+	MONO_ENTER_GC_SAFE;
+
 	/* Use the SIO_GET_EXTENSION_FUNCTION_POINTER to determine
 	 * the address of the disconnect method without taking
 	 * a hard dependency on a single provider
@@ -259,36 +286,54 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse)
 	GUID disconnect_guid = WSAID_DISCONNECTEX;
 	ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &disconnect_guid, sizeof (GUID), &disconnect, sizeof (LPFN_DISCONNECTEX), &output_bytes, NULL, NULL);
 	if (ret == 0) {
-		if (!disconnect (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0))
-			return WSAGetLastError ();
+		if (!disconnect (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0)) {
+			ret = WSAGetLastError ();
+			goto done;
+		}
 
-		return 0;
+		ret = 0;
+		goto done;
 	}
 
 	GUID transmit_file_guid = WSAID_TRANSMITFILE;
 	ret = WSAIoctl (sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &transmit_file_guid, sizeof (GUID), &transmit_file, sizeof (LPFN_TRANSMITFILE), &output_bytes, NULL, NULL);
 	if (ret == 0) {
-		if (!transmit_file (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0)))
-			return WSAGetLastError ();
+		if (!transmit_file (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0))) {
+			ret = WSAGetLastError ();
+			goto done;
+		}
 
-		return 0;
+		ret = 0;
+		goto done;
 	}
 
-	return ERROR_NOT_SUPPORTED;
+	ret = ERROR_NOT_SUPPORTED;
+
+done:
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 #endif /* #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
 gint
 mono_w32socket_set_blocking (SOCKET sock, gboolean blocking)
 {
+	gint ret;
 	gulong nonblocking_long = !blocking;
-	return ioctlsocket (sock, FIONBIO, &nonblocking_long);
+	MONO_ENTER_GC_SAFE;
+	ret = ioctlsocket (sock, FIONBIO, &nonblocking_long);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 gint
 mono_w32socket_get_available (SOCKET sock, guint64 *amount)
 {
-	return ioctlsocket (sock, FIONREAD, (int*) amount);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = ioctlsocket (sock, FIONREAD, (int*) amount);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 void
@@ -315,3 +360,15 @@ ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, Mo
 	error_init (error);
 	return TRUE;
 }
+
+gboolean
+mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle)
+{
+	gboolean ret;
+
+	MONO_ENTER_GC_SAFE;
+	ret = DuplicateHandle (GetCurrentProcess(), handle, GINT_TO_POINTER(targetProcessId), duplicate_handle, 0, 0, 0x00000002 /* DUPLICATE_SAME_ACCESS */);
+	MONO_EXIT_GC_SAFE;
+
+	return ret;
+}

+ 68 - 70
mono/metadata/w32socket.c

@@ -116,61 +116,101 @@ create_sockaddr_from_handle (MonoObjectHandle saddr_obj, socklen_t *sa_size, gin
 static SOCKET
 mono_w32socket_socket (int domain, int type, int protocol)
 {
-	return WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
+	SOCKET ret;
+	MONO_ENTER_GC_SAFE;
+	ret = WSASocket (domain, type, protocol, NULL, 0, WSA_FLAG_OVERLAPPED);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen)
 {
-	return bind (sock, addr, addrlen);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = bind (sock, addr, addrlen);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
 {
-	return getpeername (sock, name, namelen);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = getpeername (sock, name, namelen);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
 {
-	return getsockname (sock, name, namelen);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = getsockname (sock, name, namelen);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen)
 {
-	return getsockopt (sock, level, optname, optval, optlen);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = getsockopt (sock, level, optname, optval, optlen);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
 {
-	return setsockopt (sock, level, optname, optval, optlen);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = setsockopt (sock, level, optname, optval, optlen);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_listen (SOCKET sock, gint backlog)
 {
-	return listen (sock, backlog);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = listen (sock, backlog);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_shutdown (SOCKET sock, gint how)
 {
-	return shutdown (sock, how);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = shutdown (sock, how);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gint
 mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
 {
-	return WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL);
+	gint ret;
+	MONO_ENTER_GC_SAFE;
+	ret = WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 static gboolean
 mono_w32socket_close (SOCKET sock)
 {
-	return CloseHandle (sock);
+	gboolean ret;
+	MONO_ENTER_GC_SAFE;
+	ret = CloseHandle (sock);
+	MONO_EXIT_GC_SAFE;
+	return ret;
 }
 
 #endif /* HOST_WIN32 */
@@ -745,9 +785,7 @@ ves_icall_System_Net_Sockets_Socket_Close_internal (gsize sock, gint32 *werror,
 	 * polling system does not notify when the socket is closed */
 	mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock));
 
-	MONO_ENTER_GC_SAFE;
 	mono_w32socket_close ((SOCKET) sock);
-	MONO_EXIT_GC_SAFE;
 }
 
 gint32
@@ -805,10 +843,7 @@ ves_icall_System_Net_Sockets_Socket_Accept_internal (gsize sock, gint32 *werror,
 		return NULL;
 	}
 
-	MONO_ENTER_GC_SAFE;
 	newsock = mono_w32socket_accept (sock, NULL, 0, blocking);
-	MONO_EXIT_GC_SAFE;
-
 	if (newsock == INVALID_SOCKET)
 		*werror = mono_w32socket_get_last_error ();
 
@@ -830,12 +865,7 @@ ves_icall_System_Net_Sockets_Socket_Listen_internal(gsize sock, guint32 backlog,
 	error_init (error);
 	*werror = 0;
 
-	MONO_ENTER_GC_SAFE;
-
 	ret = mono_w32socket_listen (sock, backlog);
-
-	MONO_EXIT_GC_SAFE;
-
 	if (ret == SOCKET_ERROR)
 		*werror = mono_w32socket_get_last_error ();
 }
@@ -1031,12 +1061,7 @@ ves_icall_System_Net_Sockets_Socket_LocalEndPoint_internal (gsize sock, gint32 a
 	}
 	sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
 
-	MONO_ENTER_GC_SAFE;
-
 	ret = mono_w32socket_getsockname (sock, (struct sockaddr *)sa, &salen);
-
-	MONO_EXIT_GC_SAFE;
-	
 	if (ret == SOCKET_ERROR) {
 		*werror = mono_w32socket_get_last_error ();
 		if (salen > 128)
@@ -1070,12 +1095,7 @@ ves_icall_System_Net_Sockets_Socket_RemoteEndPoint_internal (gsize sock, gint32
 	sa = (salen <= 128) ? (gchar *)alloca (salen) : (gchar *)g_malloc0 (salen);
 	/* Note: linux returns just 2 for AF_UNIX. Always. */
 
-	MONO_ENTER_GC_SAFE;
-
 	ret = mono_w32socket_getpeername (sock, (struct sockaddr *)sa, &salen);
-
-	MONO_EXIT_GC_SAFE;
-
 	if (ret == SOCKET_ERROR) {
 		*werror = mono_w32socket_get_last_error ();
 		if (salen > 128)
@@ -1358,10 +1378,7 @@ ves_icall_System_Net_Sockets_Socket_Connect_internal (gsize sock, MonoObjectHand
 		return;
 	}
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_connect (sock, sa, sa_size, blocking);
-	MONO_EXIT_GC_SAFE;
-
 	if (ret == SOCKET_ERROR)
 		*werror = mono_w32socket_get_last_error ();
 
@@ -1389,9 +1406,7 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean
 		return;
 	}
 
-	MONO_ENTER_GC_SAFE;
 	*werror = mono_w32socket_disconnect (sock, reuse);
-	MONO_EXIT_GC_SAFE;
 
 	mono_thread_info_uninstall_interrupt (&interrupted);
 	if (interrupted)
@@ -1399,6 +1414,20 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean
 }
 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT) */
 
+MonoBoolean
+ves_icall_System_Net_Sockets_Socket_Duplicate_internal (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle, gint32 *werror, MonoError *error)
+{
+	error_init (error);
+
+	*werror = 0;
+	if (!mono_w32socket_duplicate (handle, targetProcessId, duplicate_handle)) {
+		*werror = mono_w32error_get_last ();
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 gint32
 ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArrayHandle buffer, gint32 offset, gint32 count, gint32 flags, gint32 *werror, gboolean blocking, MonoError *error)
 {
@@ -1428,9 +1457,7 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (gsize sock, MonoArrayHandl
 	uint32_t gchandle;
 	gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_recv (sock, buf, count, recvflags, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	mono_gchandle_free (gchandle);
 	
@@ -1475,9 +1502,7 @@ ves_icall_System_Net_Sockets_Socket_Receive_array_internal (gsize sock, MonoArra
 	uint32_t gchandle;
 	WSABUF *wsabufs = MONO_ARRAY_HANDLE_PIN (buffers, WSABUF, 0, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_recvbuffers (sock, wsabufs, count, &recv, &recvflags, NULL, NULL, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	mono_gchandle_free (gchandle);
 
@@ -1534,9 +1559,7 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (gsize sock, MonoArrayH
 	uint32_t gchandle;
 	buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_recvfrom (sock, buf, count, recvflags, sa, &sa_size, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	mono_gchandle_free (gchandle);
 
@@ -1606,9 +1629,7 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (gsize sock, MonoArrayHandle b
 	uint32_t gchandle;
 	gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_send (sock, buf, count, sendflags, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	mono_gchandle_free (gchandle);
 
@@ -1653,9 +1674,7 @@ ves_icall_System_Net_Sockets_Socket_Send_array_internal (gsize sock, MonoArrayHa
 	uint32_t gchandle;
 	WSABUF *wsabufs = MONO_ARRAY_HANDLE_PIN (buffers, WSABUF, 0, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_sendbuffers (sock, wsabufs, count, &sent, sendflags, NULL, NULL, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	mono_gchandle_free (gchandle);
 
@@ -1715,9 +1734,7 @@ ves_icall_System_Net_Sockets_Socket_SendTo_internal (gsize sock, MonoArrayHandle
 	uint32_t gchandle;
 	gchar *buf = MONO_ARRAY_HANDLE_PIN (buffer, gchar, offset, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_sendto (sock, buf, count, sendflags, sa, sa_size, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	mono_gchandle_free (gchandle);
 
@@ -1965,8 +1982,6 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gi
 		return;
 	}
 
-	MONO_ENTER_GC_SAFE;
-
 	/* No need to deal with MulticastOption names here, because
 	 * you cant getsockopt AddMembership or DropMembership (the
 	 * int getsockopt will error, causing an exception)
@@ -1992,8 +2007,6 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (gsize sock, gi
 		ret = mono_w32socket_getsockopt (sock, system_level, system_name, &val, &valsize);
 	}
 
-	MONO_EXIT_GC_SAFE;
-
 	if (ret == SOCKET_ERROR) {
 		*werror = mono_w32socket_get_last_error ();
 		return;
@@ -2111,12 +2124,8 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_arr_internal (gsize sock, gi
 	uint32_t gchandle;
 	guchar *buf = MONO_ARRAY_HANDLE_PIN (byte_val, guchar, 0, &gchandle);
 
-	MONO_ENTER_GC_SAFE;
-
 	ret = mono_w32socket_getsockopt (sock, system_level, system_name, buf, &valsize);
 
-	MONO_EXIT_GC_SAFE;
-
 	mono_gchandle_free (gchandle);
 
 	if (ret == SOCKET_ERROR)
@@ -2425,13 +2434,8 @@ ves_icall_System_Net_Sockets_Socket_Shutdown_internal (gsize sock, gint32 how, g
 		return;
 	}
 
-	MONO_ENTER_GC_SAFE;
-
 	/* Currently, the values for how (recv=0, send=1, both=2) match the BSD API */
 	ret = mono_w32socket_shutdown (sock, how);
-
-	MONO_EXIT_GC_SAFE;
-
 	if (ret == SOCKET_ERROR)
 		*werror = mono_w32socket_get_last_error ();
 
@@ -2476,12 +2480,8 @@ ves_icall_System_Net_Sockets_Socket_IOControl_internal (gsize sock, gint32 code,
 		o_buffer = MONO_ARRAY_HANDLE_PIN (output, gchar, 0, &o_gchandle);
 	}
 
-	MONO_ENTER_GC_SAFE;
-
 	ret = mono_w32socket_ioctl (sock, code, i_buffer, i_len, o_buffer, o_len, &output_bytes);
 
-	MONO_EXIT_GC_SAFE;
-
 	if (i_gchandle)
 		mono_gchandle_free (i_gchandle);
 	if (o_gchandle)
@@ -2709,14 +2709,14 @@ ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStri
 
 	g_free (address);
 
-	MONO_ENTER_GC_SAFE;
-
 	switch (family) {
 	case AF_INET: {
 #if HAVE_SOCKADDR_IN_SIN_LEN
 		saddr.sin_len = sizeof (saddr);
 #endif
+		MONO_ENTER_GC_SAFE;
 		ret = getnameinfo ((struct sockaddr*)&saddr, sizeof (saddr), hostname, sizeof (hostname), NULL, 0, 0) == 0;
+		MONO_EXIT_GC_SAFE;
 		break;
 	}
 #ifdef HAVE_STRUCT_SOCKADDR_IN6
@@ -2724,7 +2724,9 @@ ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStri
 #if HAVE_SOCKADDR_IN6_SIN_LEN
 		saddr6.sin6_len = sizeof (saddr6);
 #endif
+		MONO_ENTER_GC_SAFE;
 		ret = getnameinfo ((struct sockaddr*)&saddr6, sizeof (saddr6), hostname, sizeof (hostname), NULL, 0, 0) == 0;
+		MONO_EXIT_GC_SAFE;
 		break;
 	}
 #endif
@@ -2732,8 +2734,6 @@ ves_icall_System_Net_Dns_GetHostByAddr_internal (MonoStringHandle addr, MonoStri
 		g_assert_not_reached ();
 	}
 
-	MONO_EXIT_GC_SAFE;
-
 	if (!ret)
 		return FALSE;
 
@@ -2807,9 +2807,7 @@ ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoStringHan
 		buffers.TailLength = mono_array_handle_length (post_buffer);
 	}
 
-	MONO_ENTER_GC_SAFE;
 	ret = mono_w32socket_transmit_file (sock, file, &buffers, flags, blocking);
-	MONO_EXIT_GC_SAFE;
 
 	if (pre_buffer_gchandle)
 		mono_gchandle_free (pre_buffer_gchandle);

+ 3 - 0
mono/metadata/w32socket.h

@@ -278,6 +278,9 @@ ves_icall_System_Net_Sockets_Socket_Poll_internal (gsize sock, gint mode, gint t
 void
 ves_icall_System_Net_Sockets_Socket_Disconnect_internal (gsize sock, MonoBoolean reuse, gint32 *werror, MonoError *error);
 
+MonoBoolean
+ves_icall_System_Net_Sockets_Socket_Duplicate_internal (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle, gint32 *werror, MonoError *error);
+
 gboolean
 ves_icall_System_Net_Sockets_Socket_SendFile_internal (gsize sock, MonoStringHandle filename,
 						       MonoArrayHandle pre_buffer, MonoArrayHandle post_buffer,

Some files were not shown because too many files changed in this diff