From: Ludovic Henry Date: Mon, 7 Aug 2017 13:52:12 +0000 (+0200) Subject: [w32handle] Remove use of w32handle for File, Console, Pipe and Socket (#5319) X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mono.git;a=commitdiff_plain;h=bf3ac1d7fc45eb32c799e6fb185695c3ee2baef5 [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 --- diff --git a/mcs/class/System/System.Net.Sockets/Socket.cs b/mcs/class/System/System.Net.Sockets/Socket.cs index d19756b6c30..ae92b8d730b 100644 --- a/mcs/class/System/System.Net.Sockets/Socket.cs +++ b/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); diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am index c7fab2db8f3..95867a3e4ca 100644 --- a/mono/metadata/Makefile.am +++ b/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 = \ diff --git a/mono/metadata/fdhandle.c b/mono/metadata/fdhandle.c new file mode 100644 index 00000000000..39e531b514c --- /dev/null +++ b/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; +} diff --git a/mono/metadata/fdhandle.h b/mono/metadata/fdhandle.h new file mode 100644 index 00000000000..e3d7e5b9b98 --- /dev/null +++ b/mono/metadata/fdhandle.h @@ -0,0 +1,50 @@ + +#ifndef __MONO_METADATA_FDHANDLE_H__ +#define __MONO_METADATA_FDHANDLE_H__ + +#include +#include + +#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__ */ diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index a6a68bde499..2cc591e8c8c 100644 --- a/mono/metadata/icall-def.h +++ b/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)) diff --git a/mono/metadata/w32file-unix.c b/mono/metadata/w32file-unix.c index d74520f162c..a3ac2264f6d 100644 --- a/mono/metadata/w32file-unix.c +++ b/mono/metadata/w32file-unix.c @@ -40,6 +40,7 @@ #include "w32file-unix-glob.h" #include "w32handle.h" #include "w32error.h" +#include "fdhandle.h" #include "utils/mono-io-portability.h" #include "utils/mono-logger-internals.h" #include "utils/mono-os-mutex.h" @@ -59,14 +60,14 @@ typedef struct { /* Currently used for both FILE, CONSOLE and PIPE handle types. * This may have to change in future. */ typedef struct { + MonoFDHandle fdhandle; gchar *filename; FileShare *share_info; /* Pointer into shared mem */ - gint fd; guint32 security_attributes; guint32 fileaccess; guint32 sharemode; guint32 attrs; -} MonoW32HandleFile; +} FileHandle; typedef struct { gchar **namelist; @@ -93,6 +94,63 @@ time_t_to_filetime (time_t timeval, FILETIME *filetime) filetime->dwHighDateTime = ticks >> 32; } +static FileHandle* +file_data_create (MonoFDType type, gint fd) +{ + FileHandle *filehandle; + + filehandle = g_new0 (FileHandle, 1); + mono_fdhandle_init ((MonoFDHandle*) filehandle, type, fd); + + return filehandle; +} + +static gint +_wapi_unlink (const gchar *pathname); + +static void +file_share_release (FileShare *share_info); + +static void +file_data_close (MonoFDHandle *fdhandle) +{ + FileHandle* filehandle; + + filehandle = (FileHandle*) fdhandle; + g_assert (filehandle); + + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) filehandle)->fd); + + if (((MonoFDHandle*) filehandle)->type == MONO_FDTYPE_FILE && (filehandle->attrs & FILE_FLAG_DELETE_ON_CLOSE)) { + _wapi_unlink (filehandle->filename); + } + + if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_CONSOLE || ((MonoFDHandle*) filehandle)->fd > 2) { + if (filehandle->share_info) { + file_share_release (filehandle->share_info); + filehandle->share_info = NULL; + } + + MONO_ENTER_GC_SAFE; + close (((MonoFDHandle*) filehandle)->fd); + MONO_EXIT_GC_SAFE; + } +} + +static void +file_data_destroy (MonoFDHandle *fdhandle) +{ + FileHandle *filehandle; + + filehandle = (FileHandle*) fdhandle; + g_assert (filehandle); + + if (filehandle->filename) + g_free (filehandle->filename); + + g_free (filehandle); +} + static void file_share_release (FileShare *share_info) { @@ -102,8 +160,10 @@ file_share_release (FileShare *share_info) g_assert (share_info->handle_refs > 0); share_info->handle_refs -= 1; - if (share_info->handle_refs == 0) + if (share_info->handle_refs == 0) { g_hash_table_remove (file_share_table, share_info); + // g_free (share_info); + } mono_coop_mutex_unlock (&file_share_mutex); } @@ -803,65 +863,15 @@ _wapi_unlock_file_region (gint fd, off_t offset, off_t length) return TRUE; } -static void file_close (gpointer handle, gpointer data); -static void file_details (gpointer data); -static const gchar* file_typename (void); -static gsize file_typesize (void); -static gint file_getfiletype(void); -static gboolean file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread); -static gboolean file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten); -static gboolean file_flush(gpointer handle); -static guint32 file_seek(gpointer handle, gint32 movedistance, - gint32 *highmovedistance, gint method); -static gboolean file_setendoffile(gpointer handle); -static guint32 file_getfilesize(gpointer handle, guint32 *highsize); -static gboolean file_getfiletime(gpointer handle, FILETIME *create_time, - FILETIME *access_time, - FILETIME *write_time); -static gboolean file_setfiletime(gpointer handle, - const FILETIME *create_time, - const FILETIME *access_time, - const FILETIME *write_time); -static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name); - -/* File handle is only signalled for overlapped IO */ -static MonoW32HandleOps _wapi_file_ops = { - file_close, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL, /* prewait */ - file_details, /* details */ - file_typename, /* typename */ - file_typesize, /* typesize */ -}; - -static void console_close (gpointer handle, gpointer data); -static void console_details (gpointer data); -static const gchar* console_typename (void); -static gsize console_typesize (void); -static gint console_getfiletype(void); -static gboolean console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread); -static gboolean console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten); - -/* Console is mostly the same as file, except it can block waiting for - * input or output - */ -static MonoW32HandleOps _wapi_console_ops = { - console_close, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL, /* prewait */ - console_details, /* details */ - console_typename, /* typename */ - console_typesize, /* typesize */ -}; +static const gchar* find_typename (void) +{ + return "Find"; +} -static const gchar* find_typename (void); -static gsize find_typesize (void); +static gsize find_typesize (void) +{ + return sizeof (MonoW32HandleFind); +} static MonoW32HandleOps _wapi_find_ops = { NULL, /* close */ @@ -875,85 +885,6 @@ static MonoW32HandleOps _wapi_find_ops = { find_typesize, /* typesize */ }; -static void pipe_close (gpointer handle, gpointer data); -static void pipe_details (gpointer data); -static const gchar* pipe_typename (void); -static gsize pipe_typesize (void); -static gint pipe_getfiletype (void); -static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread); -static gboolean pipe_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten); - -/* Pipe handles - */ -static MonoW32HandleOps _wapi_pipe_ops = { - pipe_close, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL, /* prewait */ - pipe_details, /* details */ - pipe_typename, /* typename */ - pipe_typesize, /* typesize */ -}; - -static const struct { - /* File, console and pipe handles */ - gint (*getfiletype)(void); - - /* File, console and pipe handles */ - gboolean (*readfile)(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread); - gboolean (*writefile)(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten); - gboolean (*flushfile)(gpointer handle); - - /* File handles */ - guint32 (*seek)(gpointer handle, gint32 movedistance, - gint32 *highmovedistance, gint method); - gboolean (*setendoffile)(gpointer handle); - guint32 (*getfilesize)(gpointer handle, guint32 *highsize); - gboolean (*getfiletime)(gpointer handle, FILETIME *create_time, - FILETIME *access_time, - FILETIME *write_time); - gboolean (*setfiletime)(gpointer handle, - const FILETIME *create_time, - const FILETIME *access_time, - const FILETIME *write_time); -} io_ops[MONO_W32HANDLE_COUNT]={ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* file */ - {file_getfiletype, - file_read, file_write, - file_flush, file_seek, - file_setendoffile, - file_getfilesize, - file_getfiletime, - file_setfiletime}, - /* console */ - {console_getfiletype, - console_read, - console_write, - NULL, NULL, NULL, NULL, NULL, NULL}, - /* thread */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* sem */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* mutex */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* event */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* socket (will need at least read and write) */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* find */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* process */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}, - /* pipe */ - {pipe_getfiletype, - pipe_read, - pipe_write, - NULL, NULL, NULL, NULL, NULL, NULL}, -}; - static gboolean lock_while_writing = FALSE; /* Some utility functions. @@ -1087,88 +1018,18 @@ static void _wapi_set_last_path_error_from_errno (const gchar *dir, } } -/* Handle ops. - */ -static void file_close (gpointer handle, gpointer data) -{ - /* FIXME: after mono_w32handle_close is coop-aware, change this to MONO_REQ_GC_UNSAFE_MODE and leave just the switch to SAFE around close() below */ - MONO_ENTER_GC_UNSAFE; - MonoW32HandleFile *file_handle = (MonoW32HandleFile *)data; - gint fd = file_handle->fd; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing file handle %p [%s]", __func__, handle, - file_handle->filename); - - if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE) - _wapi_unlink (file_handle->filename); - - g_free (file_handle->filename); - - if (file_handle->share_info) - file_share_release (file_handle->share_info); - - MONO_ENTER_GC_SAFE; - close (fd); - MONO_EXIT_GC_SAFE; - MONO_EXIT_GC_UNSAFE; -} - -static void file_details (gpointer data) -{ - MonoW32HandleFile *file = (MonoW32HandleFile *)data; - - g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u", - file->filename, - file->fileaccess&GENERIC_READ?'R':'.', - file->fileaccess&GENERIC_WRITE?'W':'.', - file->fileaccess&GENERIC_EXECUTE?'X':'.', - file->sharemode&FILE_SHARE_READ?'R':'.', - file->sharemode&FILE_SHARE_WRITE?'W':'.', - file->sharemode&FILE_SHARE_DELETE?'D':'.', - file->attrs); -} - -static const gchar* file_typename (void) -{ - return "File"; -} - -static gsize file_typesize (void) -{ - return sizeof (MonoW32HandleFile); -} - -static gint file_getfiletype(void) -{ - return(FILE_TYPE_DISK); -} - static gboolean -file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread) +file_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleFile *file_handle; - gboolean ok; - gint fd, ret; + gint ret; MonoThreadInfo *info = mono_thread_info_current (); - - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = file_handle->fd; if(bytesread!=NULL) { *bytesread=0; } - if(!(file_handle->fileaccess & GENERIC_READ) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u", - __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1176,7 +1037,7 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread do { MONO_ENTER_GC_SAFE; - ret = read (fd, buffer, numbytes); + ret = read (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -1184,8 +1045,7 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread if(ret==-1) { gint err = errno; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, - handle, strerror(err)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(err)); mono_w32error_set_last (mono_w32error_unix_to_win32 (err)); return(FALSE); } @@ -1198,32 +1058,18 @@ file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread } static gboolean -file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +file_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleFile *file_handle; - gboolean ok; - gint ret, fd; + gint ret; off_t current_pos = 0; MonoThreadInfo *info = mono_thread_info_current (); - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - - fd = file_handle->fd; - if(byteswritten!=NULL) { *byteswritten=0; } - if(!(file_handle->fileaccess & GENERIC_WRITE) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & GENERIC_WRITE) && !(filehandle->fileaccess & GENERIC_ALL)) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1235,17 +1081,15 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt * systems */ MONO_ENTER_GC_SAFE; - current_pos = lseek (fd, (off_t)0, SEEK_CUR); + current_pos = lseek (((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR); MONO_EXIT_GC_SAFE; if (current_pos == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__, - handle, strerror (errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror (errno)); _wapi_set_last_error_from_errno (); return(FALSE); } - if (_wapi_lock_file_region (fd, current_pos, - numbytes) == FALSE) { + if (_wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes) == FALSE) { /* The error has already been set */ return(FALSE); } @@ -1253,13 +1097,13 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt do { MONO_ENTER_GC_SAFE; - ret = write (fd, buffer, numbytes); + ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (lock_while_writing) { - _wapi_unlock_file_region (fd, current_pos, numbytes); + _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, current_pos, numbytes); } if (ret == -1) { @@ -1268,8 +1112,7 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt } else { _wapi_set_last_error_from_errno (); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", - __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } @@ -1280,37 +1123,22 @@ file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt return(TRUE); } -static gboolean file_flush(gpointer handle) +static gboolean file_flush(FileHandle *filehandle) { - MonoW32HandleFile *file_handle; - gboolean ok; - gint ret, fd; - - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - - fd = file_handle->fd; + gint ret; - if(!(file_handle->fileaccess & GENERIC_WRITE) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } MONO_ENTER_GC_SAFE; - ret=fsync(fd); + ret=fsync(((MonoFDHandle*) filehandle)->fd); MONO_EXIT_GC_SAFE; if (ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1319,30 +1147,15 @@ static gboolean file_flush(gpointer handle) return(TRUE); } -static guint32 file_seek(gpointer handle, gint32 movedistance, +static guint32 file_seek(FileHandle *filehandle, gint32 movedistance, gint32 *highmovedistance, gint method) { - MonoW32HandleFile *file_handle; - gboolean ok; gint64 offset, newpos; - gint whence, fd; + gint whence; guint32 ret; - - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(INVALID_SET_FILE_POINTER); - } - - fd = file_handle->fd; - if(!(file_handle->fileaccess & GENERIC_READ) && - !(file_handle->fileaccess & GENERIC_WRITE) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(INVALID_SET_FILE_POINTER); @@ -1380,22 +1193,20 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, offset=movedistance; #endif - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %" G_GINT64_FORMAT " bytes from %d", __func__, - handle, offset, whence); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving fd %d by %" G_GINT64_FORMAT " bytes from %d", __func__, ((MonoFDHandle*) filehandle)->fd, offset, whence); #ifdef PLATFORM_ANDROID /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */ MONO_ENTER_GC_SAFE; - newpos=lseek64(fd, offset, whence); + newpos=lseek64(((MonoFDHandle*) filehandle)->fd, offset, whence); MONO_EXIT_GC_SAFE; #else MONO_ENTER_GC_SAFE; - newpos=lseek(fd, offset, whence); + newpos=lseek(((MonoFDHandle*) filehandle)->fd, offset, whence); MONO_EXIT_GC_SAFE; #endif if(newpos==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s", - __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on fd %d returned error %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(INVALID_SET_FILE_POINTER); @@ -1416,34 +1227,20 @@ static guint32 file_seek(gpointer handle, gint32 movedistance, } #endif - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %" G_GUINT32_FORMAT "/%" G_GINT32_FORMAT, __func__, - handle, ret, highmovedistance==NULL?0:*highmovedistance); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of fd %d returning %" G_GUINT32_FORMAT "/%" G_GINT32_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, ret, highmovedistance==NULL?0:*highmovedistance); return(ret); } -static gboolean file_setendoffile(gpointer handle) +static gboolean file_setendoffile(FileHandle *filehandle) { - MonoW32HandleFile *file_handle; - gboolean ok; struct stat statbuf; off_t pos; - gint ret, fd; + gint ret; MonoThreadInfo *info = mono_thread_info_current (); - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = file_handle->fd; - - if(!(file_handle->fileaccess & GENERIC_WRITE) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1456,22 +1253,20 @@ static gboolean file_setendoffile(gpointer handle) */ MONO_ENTER_GC_SAFE; - ret=fstat(fd, &statbuf); + ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf); MONO_EXIT_GC_SAFE; if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); } MONO_ENTER_GC_SAFE; - pos=lseek(fd, (off_t)0, SEEK_CUR); + pos=lseek(((MonoFDHandle*) filehandle)->fd, (off_t)0, SEEK_CUR); MONO_EXIT_GC_SAFE; if(pos==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1493,13 +1288,13 @@ static gboolean file_setendoffile(gpointer handle) */ do { MONO_ENTER_GC_SAFE; - ret = write (fd, "", 1); + ret = write (((MonoFDHandle*) filehandle)->fd, "", 1); MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p extend write failed: %s", __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d extend write failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1507,11 +1302,10 @@ static gboolean file_setendoffile(gpointer handle) /* And put the file position back after the write */ MONO_ENTER_GC_SAFE; - ret = lseek (fd, pos, SEEK_SET); + ret = lseek (((MonoFDHandle*) filehandle)->fd, pos, SEEK_SET); MONO_EXIT_GC_SAFE; if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s", - __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d second lseek failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1524,13 +1318,12 @@ static gboolean file_setendoffile(gpointer handle) */ do { MONO_ENTER_GC_SAFE; - ret=ftruncate(fd, pos); + ret=ftruncate(((MonoFDHandle*) filehandle)->fd, pos); MONO_EXIT_GC_SAFE; } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ftruncate failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ftruncate failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1539,29 +1332,14 @@ static gboolean file_setendoffile(gpointer handle) return(TRUE); } -static guint32 file_getfilesize(gpointer handle, guint32 *highsize) +static guint32 file_getfilesize(FileHandle *filehandle, guint32 *highsize) { - MonoW32HandleFile *file_handle; - gboolean ok; struct stat statbuf; guint32 size; gint ret; - gint fd; - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(INVALID_FILE_SIZE); - } - fd = file_handle->fd; - - if(!(file_handle->fileaccess & GENERIC_READ) && - !(file_handle->fileaccess & GENERIC_WRITE) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(INVALID_FILE_SIZE); @@ -1574,11 +1352,10 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) mono_w32error_set_last (ERROR_SUCCESS); MONO_ENTER_GC_SAFE; - ret = fstat(fd, &statbuf); + ret = fstat(((MonoFDHandle*) filehandle)->fd, &statbuf); MONO_EXIT_GC_SAFE; if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(INVALID_FILE_SIZE); @@ -1590,11 +1367,10 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) guint64 bigsize; gint res; MONO_ENTER_GC_SAFE; - res = ioctl (fd, BLKGETSIZE64, &bigsize); + res = ioctl (((MonoFDHandle*) filehandle)->fd, BLKGETSIZE64, &bigsize); MONO_EXIT_GC_SAFE; if (res < 0) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s", - __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d ioctl BLKGETSIZE64 failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(INVALID_FILE_SIZE); @@ -1630,41 +1406,26 @@ static guint32 file_getfilesize(gpointer handle, guint32 *highsize) return(size); } -static gboolean file_getfiletime(gpointer handle, FILETIME *create_time, +static gboolean file_getfiletime(FileHandle *filehandle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time) { - MonoW32HandleFile *file_handle; - gboolean ok; struct stat statbuf; guint64 create_ticks, access_ticks, write_ticks; - gint ret, fd; - - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = file_handle->fd; + gint ret; - if(!(file_handle->fileaccess & GENERIC_READ) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u", - __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } MONO_ENTER_GC_SAFE; - ret=fstat(fd, &statbuf); + ret=fstat(((MonoFDHandle*) filehandle)->fd, &statbuf); MONO_EXIT_GC_SAFE; if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1712,38 +1473,26 @@ static gboolean file_getfiletime(gpointer handle, FILETIME *create_time, return(TRUE); } -static gboolean file_setfiletime(gpointer handle, +static gboolean file_setfiletime(FileHandle *filehandle, const FILETIME *create_time G_GNUC_UNUSED, const FILETIME *access_time, const FILETIME *write_time) { - MonoW32HandleFile *file_handle; - gboolean ok; struct utimbuf utbuf; struct stat statbuf; guint64 access_ticks, write_ticks; - gint ret, fd; + gint ret; - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, - (gpointer *)&file_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up file handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = file_handle->fd; - if(!(file_handle->fileaccess & GENERIC_WRITE) && - !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - if(file_handle->filename == NULL) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle); + if(filehandle->filename == NULL) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d unknown filename", __func__, ((MonoFDHandle*) filehandle)->fd); mono_w32error_set_last (ERROR_INVALID_HANDLE); return(FALSE); @@ -1753,11 +1502,10 @@ static gboolean file_setfiletime(gpointer handle, * the event that one of the FileTime structs is NULL */ MONO_ENTER_GC_SAFE; - ret=fstat (fd, &statbuf); + ret=fstat (((MonoFDHandle*) filehandle)->fd, &statbuf); MONO_EXIT_GC_SAFE; if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d fstat failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); mono_w32error_set_last (ERROR_INVALID_PARAMETER); return(FALSE); @@ -1812,13 +1560,12 @@ static gboolean file_setfiletime(gpointer handle, utbuf.modtime=statbuf.st_mtime; } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__, - handle, utbuf.actime, utbuf.modtime); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting fd %d access %ld write %ld", __func__, + ((MonoFDHandle*) filehandle)->fd, utbuf.actime, utbuf.modtime); - ret = _wapi_utime (file_handle->filename, &utbuf); + ret = _wapi_utime (filehandle->filename, &utbuf); if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p [%s] utime failed: %s", __func__, - handle, file_handle->filename, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d [%s] utime failed: %s", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->filename, g_strerror(errno)); mono_w32error_set_last (ERROR_INVALID_PARAMETER); return(FALSE); @@ -1827,73 +1574,18 @@ static gboolean file_setfiletime(gpointer handle, return(TRUE); } -static void console_close (gpointer handle, gpointer data) -{ - /* FIXME: after mono_w32handle_close is coop-aware, change this to MONO_REQ_GC_UNSAFE_MODE and leave just the switch to SAFE around close() below */ - MONO_ENTER_GC_UNSAFE; - MonoW32HandleFile *console_handle = (MonoW32HandleFile *)data; - gint fd = console_handle->fd; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing console handle %p", __func__, handle); - - g_free (console_handle->filename); - - if (fd > 2) { - if (console_handle->share_info) - file_share_release (console_handle->share_info); - MONO_ENTER_GC_SAFE; - close (fd); - MONO_EXIT_GC_SAFE; - } - MONO_EXIT_GC_UNSAFE; -} - -static void console_details (gpointer data) -{ - file_details (data); -} - -static const gchar* console_typename (void) -{ - return "Console"; -} - -static gsize console_typesize (void) -{ - return sizeof (MonoW32HandleFile); -} - -static gint console_getfiletype(void) -{ - return(FILE_TYPE_CHAR); -} - static gboolean -console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread) +console_read(FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleFile *console_handle; - gboolean ok; - gint ret, fd; + gint ret; MonoThreadInfo *info = mono_thread_info_current (); - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE, - (gpointer *)&console_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up console handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = console_handle->fd; - if(bytesread!=NULL) { *bytesread=0; } - if(!(console_handle->fileaccess & GENERIC_READ) && - !(console_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u", - __func__, handle, console_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1901,13 +1593,12 @@ console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesr do { MONO_ENTER_GC_SAFE; - ret=read(fd, buffer, numbytes); + ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); MONO_EXIT_GC_SAFE; } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, handle, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); _wapi_set_last_error_from_errno (); return(FALSE); @@ -1921,30 +1612,17 @@ console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesr } static gboolean -console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +console_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleFile *console_handle; - gboolean ok; - gint ret, fd; + gint ret; MonoThreadInfo *info = mono_thread_info_current (); - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE, - (gpointer *)&console_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up console handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = console_handle->fd; - if(byteswritten!=NULL) { *byteswritten=0; } - if(!(console_handle->fileaccess & GENERIC_WRITE) && - !(console_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); @@ -1952,7 +1630,7 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 * do { MONO_ENTER_GC_SAFE; - ret = write(fd, buffer, numbytes); + ret = write(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -1963,8 +1641,7 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 * } else { _wapi_set_last_error_from_errno (); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", - __func__, handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__, ((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } @@ -1976,93 +1653,28 @@ console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 * return(TRUE); } -static const gchar* find_typename (void) -{ - return "Find"; -} - -static gsize find_typesize (void) -{ - return sizeof (MonoW32HandleFind); -} - -static void pipe_close (gpointer handle, gpointer data) -{ - /* FIXME: after mono_w32handle_close is coop-aware, change this to MONO_REQ_GC_UNSAFE_MODE and leave just the switch to SAFE around close() below */ - MONO_ENTER_GC_UNSAFE; - MonoW32HandleFile *pipe_handle = (MonoW32HandleFile*)data; - gint fd = pipe_handle->fd; - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p fd %d", __func__, handle, fd); - - /* No filename with pipe handles */ - - if (pipe_handle->share_info) - file_share_release (pipe_handle->share_info); - - MONO_ENTER_GC_SAFE; - close (fd); - MONO_EXIT_GC_SAFE; - MONO_EXIT_GC_UNSAFE; -} - -static void pipe_details (gpointer data) -{ - file_details (data); -} - -static const gchar* pipe_typename (void) -{ - return "Pipe"; -} - -static gsize pipe_typesize (void) -{ - return sizeof (MonoW32HandleFile); -} - -static gint pipe_getfiletype(void) -{ - return(FILE_TYPE_PIPE); -} - static gboolean -pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread) +pipe_read (FileHandle *filehandle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleFile *pipe_handle; - gboolean ok; - gint ret, fd; + gint ret; MonoThreadInfo *info = mono_thread_info_current (); - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE, - (gpointer *)&pipe_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up pipe handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = pipe_handle->fd; - if(bytesread!=NULL) { *bytesread=0; } - if(!(pipe_handle->fileaccess & GENERIC_READ) && - !(pipe_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u", - __func__, handle, pipe_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_READ | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %" G_GUINT32_FORMAT " bytes from pipe %p", __func__, - numbytes, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %" G_GUINT32_FORMAT " bytes from pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd); do { MONO_ENTER_GC_SAFE; - ret=read(fd, buffer, numbytes); + ret=read(((MonoFDHandle*) filehandle)->fd, buffer, numbytes); MONO_EXIT_GC_SAFE; } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -2072,14 +1684,13 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea } else { _wapi_set_last_error_from_errno (); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %d", __func__, ret, ((MonoFDHandle*) filehandle)->fd); if(bytesread!=NULL) { *bytesread=ret; @@ -2089,41 +1700,27 @@ pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesrea } static gboolean -pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) +pipe_write(FileHandle *filehandle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleFile *pipe_handle; - gboolean ok; - gint ret, fd; + gint ret; MonoThreadInfo *info = mono_thread_info_current (); - ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE, - (gpointer *)&pipe_handle); - if(ok==FALSE) { - g_warning ("%s: error looking up pipe handle %p", __func__, - handle); - mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); - } - fd = pipe_handle->fd; - if(byteswritten!=NULL) { *byteswritten=0; } - if(!(pipe_handle->fileaccess & GENERIC_WRITE) && - !(pipe_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess); + if(!(filehandle->fileaccess & (GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); return(FALSE); } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %" G_GUINT32_FORMAT " bytes to pipe %p", __func__, - numbytes, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %" G_GUINT32_FORMAT " bytes to pipe %d", __func__, numbytes, ((MonoFDHandle*) filehandle)->fd); do { MONO_ENTER_GC_SAFE; - ret = write (fd, buffer, numbytes); + ret = write (((MonoFDHandle*) filehandle)->fd, buffer, numbytes); MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -2134,8 +1731,7 @@ pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byt } else { _wapi_set_last_error_from_errno (); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__, - handle, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of fd %d error: %s", __func__,((MonoFDHandle*) filehandle)->fd, g_strerror(errno)); return(FALSE); } @@ -2226,6 +1822,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing = NONE", __func__, fileaccess); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2238,6 +1835,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing: 0x%" PRIx32, __func__, fileaccess, file_existing_share); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2250,6 +1848,7 @@ static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode, mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%" PRIx32 ", file has access: 0x%" PRIx32, __func__, sharemode, file_existing_access); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2279,6 +1878,7 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info) mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing = NONE", __func__, (*share_info)->access); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2288,6 +1888,7 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info) mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%" PRIx32 ", file has sharing: 0x%" PRIx32, __func__, (*share_info)->access, file_existing_share); file_share_release (*share_info); + *share_info = NULL; return(FALSE); } @@ -2301,8 +1902,8 @@ share_allows_delete (struct stat *statbuf, FileShare **share_info) gpointer mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs) { - MonoW32HandleFile file_handle = {0}; - gpointer handle; + FileHandle *filehandle; + MonoFDType type; gint flags=convert_flags(fileaccess, createmode); /*mode_t perms=convert_perms(sharemode);*/ /* we don't use sharemode, because that relates to sharing of @@ -2313,7 +1914,6 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode mode_t perms=0666; gchar *filename; gint fd, ret; - MonoW32HandleType handle_type; struct stat statbuf; if (attrs & FILE_ATTRIBUTE_TEMPORARY) @@ -2359,81 +1959,77 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode } if (fd == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename, - strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename, g_strerror(errno)); _wapi_set_last_path_error_from_errno (NULL, filename); g_free (filename); return(INVALID_HANDLE_VALUE); } - if (fd >= mono_w32handle_fd_reserve) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); - - mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES); - - MONO_ENTER_GC_SAFE; - close (fd); - MONO_EXIT_GC_SAFE; - g_free (filename); - - return(INVALID_HANDLE_VALUE); - } - MONO_ENTER_GC_SAFE; ret = fstat (fd, &statbuf); MONO_EXIT_GC_SAFE; if (ret == -1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__, - filename, strerror (errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__, filename, g_strerror (errno)); _wapi_set_last_error_from_errno (); - g_free (filename); MONO_ENTER_GC_SAFE; close (fd); MONO_EXIT_GC_SAFE; - + return(INVALID_HANDLE_VALUE); } - if (share_allows_open (&statbuf, sharemode, fileaccess, - &file_handle.share_info) == FALSE) { - mono_w32error_set_last (ERROR_SHARING_VIOLATION); +#ifndef S_ISFIFO +#define S_ISFIFO(m) ((m & S_IFIFO) != 0) +#endif + if (S_ISFIFO (statbuf.st_mode)) { + type = MONO_FDTYPE_PIPE; + /* maintain invariant that pipes have no filename */ g_free (filename); + filename = NULL; + } else if (S_ISCHR (statbuf.st_mode)) { + type = MONO_FDTYPE_CONSOLE; + } else { + type = MONO_FDTYPE_FILE; + } + + filehandle = file_data_create (type, fd); + filehandle->filename = filename; + filehandle->fileaccess = fileaccess; + filehandle->sharemode = sharemode; + filehandle->attrs = attrs; + + if (!share_allows_open (&statbuf, filehandle->sharemode, filehandle->fileaccess, &filehandle->share_info)) { + mono_w32error_set_last (ERROR_SHARING_VIOLATION); MONO_ENTER_GC_SAFE; - close (fd); + close (((MonoFDHandle*) filehandle)->fd); MONO_EXIT_GC_SAFE; + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return (INVALID_HANDLE_VALUE); } - if (file_handle.share_info == NULL) { + if (!filehandle->share_info) { /* No space, so no more files can be opened */ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__); mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES); MONO_ENTER_GC_SAFE; - close (fd); + close (((MonoFDHandle*) filehandle)->fd); MONO_EXIT_GC_SAFE; - g_free (filename); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return(INVALID_HANDLE_VALUE); } - - file_handle.filename = filename; - - file_handle.fd = fd; - file_handle.fileaccess=fileaccess; - file_handle.sharemode=sharemode; - file_handle.attrs=attrs; #ifdef HAVE_POSIX_FADVISE if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) { MONO_ENTER_GC_SAFE; - posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL); + posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_SEQUENTIAL); MONO_EXIT_GC_SAFE; } if (attrs & FILE_FLAG_RANDOM_ACCESS) { MONO_ENTER_GC_SAFE; - posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM); + posix_fadvise (((MonoFDHandle*) filehandle)->fd, 0, 0, POSIX_FADV_RANDOM); MONO_EXIT_GC_SAFE; } #endif @@ -2441,56 +2037,27 @@ mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode #ifdef F_RDAHEAD if (attrs & FILE_FLAG_SEQUENTIAL_SCAN) { MONO_ENTER_GC_SAFE; - fcntl(fd, F_RDAHEAD, 1); + fcntl(((MonoFDHandle*) filehandle)->fd, F_RDAHEAD, 1); MONO_EXIT_GC_SAFE; } #endif -#ifndef S_ISFIFO -#define S_ISFIFO(m) ((m & S_IFIFO) != 0) -#endif - if (S_ISFIFO (statbuf.st_mode)) { - handle_type = MONO_W32HANDLE_PIPE; - /* maintain invariant that pipes have no filename */ - file_handle.filename = NULL; - g_free (filename); - filename = NULL; - } else if (S_ISCHR (statbuf.st_mode)) { - handle_type = MONO_W32HANDLE_CONSOLE; - } else { - handle_type = MONO_W32HANDLE_FILE; - } + mono_fdhandle_insert ((MonoFDHandle*) filehandle); - MONO_ENTER_GC_SAFE; /* FIXME: mono_w32handle_new_fd should be updated with coop transitions */ - handle = mono_w32handle_new_fd (handle_type, fd, &file_handle); - MONO_EXIT_GC_SAFE; - if (handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating file handle", __func__); - g_free (filename); - MONO_ENTER_GC_SAFE; - close (fd); - MONO_EXIT_GC_SAFE; - - mono_w32error_set_last (ERROR_GEN_FAILURE); - return(INVALID_HANDLE_VALUE); - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle); - - return(handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd)); + + return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd); } gboolean mono_w32file_close (gpointer handle) { - gboolean res; - MONO_ENTER_GC_SAFE; - /* FIXME: we transition here and not in file_close, pipe_close, - * console_close because w32handle_close is not coop aware yet, but it - * calls back into w32file. */ - res = mono_w32handle_close (handle); - MONO_EXIT_GC_SAFE; - return res; + if (!mono_fdhandle_close (GPOINTER_TO_INT (handle))) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + return TRUE; } gboolean mono_w32file_delete(const gunichar2 *name) @@ -2644,8 +2211,10 @@ MoveFile (gunichar2 *name, gunichar2 *dest_name) mono_w32error_set_last (ERROR_SHARING_VIOLATION); return FALSE; } - if (shareinfo) + if (shareinfo) { file_share_release (shareinfo); + shareinfo = NULL; + } result = _wapi_rename (utf8_name, utf8_dest_name); errno_copy = errno; @@ -2879,7 +2448,7 @@ CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_ex ret_utime = utime (utf8_dest, &dest_time); MONO_EXIT_GC_SAFE; if (ret_utime == -1) - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, g_strerror(errno)); g_free (utf8_src); g_free (utf8_dest); @@ -2970,14 +2539,11 @@ replace_cleanup: return ret; } -static MonoCoopMutex stdhandle_mutex; - static gpointer _wapi_stdhandle_create (gint fd, const gchar *name) { - gpointer handle; gint flags; - MonoW32HandleFile file_handle = {0}; + FileHandle *filehandle; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd); @@ -2990,52 +2556,52 @@ _wapi_stdhandle_create (gint fd, const gchar *name) /* Invalid fd. Not really much point checking for EBADF * specifically */ - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, strerror(errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, g_strerror(errno)); mono_w32error_set_last (mono_w32error_unix_to_win32 (errno)); return INVALID_HANDLE_VALUE; } + filehandle = file_data_create (MONO_FDTYPE_CONSOLE, fd); + filehandle->filename = g_strdup(name); + switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) { case O_RDONLY: - file_handle.fileaccess = GENERIC_READ; + filehandle->fileaccess = GENERIC_READ; break; case O_WRONLY: - file_handle.fileaccess = GENERIC_WRITE; + filehandle->fileaccess = GENERIC_WRITE; break; case O_RDWR: - file_handle.fileaccess = GENERIC_READ | GENERIC_WRITE; + filehandle->fileaccess = GENERIC_READ | GENERIC_WRITE; break; default: mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags); - file_handle.fileaccess = 0; + filehandle->fileaccess = 0; break; } - file_handle.fd = fd; - file_handle.filename = g_strdup(name); /* some default security attributes might be needed */ - file_handle.security_attributes = 0; + filehandle->security_attributes = 0; /* Apparently input handles can't be written to. (I don't * know if output or error handles can't be read from.) */ if (fd == 0) - file_handle.fileaccess &= ~GENERIC_WRITE; + filehandle->fileaccess &= ~GENERIC_WRITE; - file_handle.sharemode = 0; - file_handle.attrs = 0; + filehandle->sharemode = 0; + filehandle->attrs = 0; - handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle); - if (handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating file handle", __func__); - mono_w32error_set_last (ERROR_GEN_FAILURE); - return INVALID_HANDLE_VALUE; + if (!mono_fdhandle_try_insert ((MonoFDHandle*) filehandle)) { + /* we raced between 2 invocations of _wapi_stdhandle_create */ + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return GINT_TO_POINTER(fd); } - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd)); - return handle; + return GINT_TO_POINTER(((MonoFDHandle*) filehandle)->fd); } enum { @@ -3047,11 +2613,9 @@ enum { static gpointer mono_w32file_get_std_handle (gint stdhandle) { - MonoW32HandleFile *file_handle; - gpointer handle; + FileHandle **filehandle; gint fd; const gchar *name; - gboolean ok; switch(stdhandle) { case STD_INPUT_HANDLE: @@ -3073,164 +2637,260 @@ mono_w32file_get_std_handle (gint stdhandle) g_assert_not_reached (); } - handle = GINT_TO_POINTER (fd); - - mono_coop_mutex_lock (&stdhandle_mutex); + if (!mono_fdhandle_lookup_and_ref(fd, (MonoFDHandle**) &filehandle)) { + gpointer handle; - ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE, - (gpointer *)&file_handle); - if (ok == FALSE) { - /* Need to create this console handle */ handle = _wapi_stdhandle_create (fd, name); - if (handle == INVALID_HANDLE_VALUE) { mono_w32error_set_last (ERROR_NO_MORE_FILES); - goto done; + return INVALID_HANDLE_VALUE; } } - - done: - mono_coop_mutex_unlock (&stdhandle_mutex); - return(handle); + return GINT_TO_POINTER (fd); } gboolean mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if(io_ops[type].readfile==NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].readfile (handle, buffer, numbytes, bytesread)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_read(filehandle, buffer, numbytes, bytesread); + break; + case MONO_FDTYPE_CONSOLE: + ret = console_read(filehandle, buffer, numbytes, bytesread); + break; + case MONO_FDTYPE_PIPE: + ret = pipe_read(filehandle, buffer, numbytes, bytesread); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if(io_ops[type].writefile==NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_write(filehandle, buffer, numbytes, byteswritten); + break; + case MONO_FDTYPE_CONSOLE: + ret = console_write(filehandle, buffer, numbytes, byteswritten); + break; + case MONO_FDTYPE_PIPE: + ret = pipe_write(filehandle, buffer, numbytes, byteswritten); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_flush (gpointer handle) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if(io_ops[type].flushfile==NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].flushfile (handle)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_flush(filehandle); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_truncate (gpointer handle) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].setendoffile == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].setendoffile (handle)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_setendoffile(filehandle); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } guint32 mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method) { - MonoW32HandleType type; + FileHandle *filehandle; + guint32 ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].seek == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(INVALID_SET_FILE_POINTER); + return INVALID_SET_FILE_POINTER; } - - return(io_ops[type].seek (handle, movedistance, highmovedistance, - method)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_seek(filehandle, movedistance, highmovedistance, method); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return INVALID_SET_FILE_POINTER; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gint mono_w32file_get_type(gpointer handle) { - MonoW32HandleType type; + FileHandle *filehandle; + gint ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].getfiletype == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FILE_TYPE_UNKNOWN); + return FILE_TYPE_UNKNOWN; } - - return(io_ops[type].getfiletype ()); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = FILE_TYPE_DISK; + break; + case MONO_FDTYPE_CONSOLE: + ret = FILE_TYPE_CHAR; + break; + case MONO_FDTYPE_PIPE: + ret = FILE_TYPE_PIPE; + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FILE_TYPE_UNKNOWN; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } static guint32 GetFileSize(gpointer handle, guint32 *highsize) { - MonoW32HandleType type; + FileHandle *filehandle; + guint32 ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].getfilesize == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(INVALID_FILE_SIZE); + return INVALID_FILE_SIZE; } - - return(io_ops[type].getfilesize (handle, highsize)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_getfilesize(filehandle, highsize); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return INVALID_FILE_SIZE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_get_times(gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].getfiletime == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].getfiletime (handle, create_time, access_time, - write_time)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_getfiletime(filehandle, create_time, access_time, write_time); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } gboolean mono_w32file_set_times(gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time) { - MonoW32HandleType type; + FileHandle *filehandle; + gboolean ret; - type = mono_w32handle_get_type (handle); - - if (io_ops[type].setfiletime == NULL) { + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); - return(FALSE); + return FALSE; } - - return(io_ops[type].setfiletime (handle, create_time, access_time, - write_time)); + + switch (((MonoFDHandle*) filehandle)->type) { + case MONO_FDTYPE_FILE: + ret = file_setfiletime(filehandle, create_time, access_time, write_time); + break; + default: + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } /* A tick is a 100-nanosecond interval. File time epoch is Midnight, @@ -3936,10 +3596,7 @@ mono_w32file_set_cwd (const gunichar2 *path) gboolean mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size) { - MonoW32HandleFile pipe_read_handle = {0}; - MonoW32HandleFile pipe_write_handle = {0}; - gpointer read_handle; - gpointer write_handle; + FileHandle *read_filehandle, *write_filehandle; gint filedes[2]; gint ret; @@ -3948,68 +3605,30 @@ mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size) MONO_ENTER_GC_SAFE; ret=pipe (filedes); MONO_EXIT_GC_SAFE; - if(ret==-1) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__, - strerror (errno)); - + if (ret==-1) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: (%d) %s", + __func__, errno, g_strerror (errno)); + _wapi_set_last_error_from_errno (); - return(FALSE); + return FALSE; } - if (filedes[0] >= mono_w32handle_fd_reserve || - filedes[1] >= mono_w32handle_fd_reserve) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); - - mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES); - - MONO_ENTER_GC_SAFE; - close (filedes[0]); - close (filedes[1]); - MONO_EXIT_GC_SAFE; - - return(FALSE); - } - /* filedes[0] is open for reading, filedes[1] for writing */ - pipe_read_handle.fd = filedes [0]; - pipe_read_handle.fileaccess = GENERIC_READ; - read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0], - &pipe_read_handle); - if (read_handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating pipe read handle", __func__); - MONO_ENTER_GC_SAFE; - close (filedes[0]); - close (filedes[1]); - MONO_EXIT_GC_SAFE; - mono_w32error_set_last (ERROR_GEN_FAILURE); - - return(FALSE); - } - - pipe_write_handle.fd = filedes [1]; - pipe_write_handle.fileaccess = GENERIC_WRITE; - write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1], - &pipe_write_handle); - if (write_handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating pipe write handle", __func__); + read_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[0]); + read_filehandle->fileaccess = GENERIC_READ; - MONO_ENTER_GC_SAFE; - mono_w32handle_close (read_handle); - - close (filedes[0]); - close (filedes[1]); - MONO_EXIT_GC_SAFE; - mono_w32error_set_last (ERROR_GEN_FAILURE); - - return(FALSE); - } - - *readpipe = read_handle; - *writepipe = write_handle; + write_filehandle = file_data_create (MONO_FDTYPE_PIPE, filedes[1]); + write_filehandle->fileaccess = GENERIC_WRITE; + + mono_fdhandle_insert ((MonoFDHandle*) read_filehandle); + mono_fdhandle_insert ((MonoFDHandle*) write_filehandle); + + *readpipe = GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd); + *writepipe = GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p", - __func__, read_handle, write_handle); + __func__, GINT_TO_POINTER(((MonoFDHandle*) read_filehandle)->fd), GINT_TO_POINTER(((MonoFDHandle*) write_filehandle)->fd)); return(TRUE); } @@ -4563,7 +4182,7 @@ mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_byte if (ret == -1) { _wapi_set_last_error_from_errno (); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, g_strerror (errno)); return(FALSE); } @@ -4952,18 +4571,25 @@ mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumenam static gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high) { - MonoW32HandleFile *file_handle; + FileHandle *filehandle; + gboolean ret; off_t offset, length; - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) { - g_warning ("%s: error looking up file handle %p", __func__, handle); + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_FILE) { mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return FALSE; } - if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if (!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return FALSE; } @@ -4971,38 +4597,48 @@ LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 leng offset = ((gint64)offset_high << 32) | offset_low; length = ((gint64)length_high << 32) | length_low; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, - handle, (gint64) offset, (gint64) length); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #else if (offset_high > 0 || length_high > 0) { mono_w32error_set_last (ERROR_INVALID_PARAMETER); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return FALSE; } + offset = offset_low; length = length_low; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, - handle, (gint64) offset, (gint64) length); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #endif - return _wapi_lock_file_region (GPOINTER_TO_UINT(handle), offset, length); + ret = _wapi_lock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length); + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } static gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high) { - MonoW32HandleFile *file_handle; + FileHandle *filehandle; + gboolean ret; off_t offset, length; - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) { - g_warning ("%s: error looking up file handle %p", __func__, handle); + if (!mono_fdhandle_lookup_and_ref(GPOINTER_TO_INT(handle), (MonoFDHandle**) &filehandle)) { mono_w32error_set_last (ERROR_INVALID_HANDLE); return FALSE; } - if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess); + if (((MonoFDHandle*) filehandle)->type != MONO_FDTYPE_FILE) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return FALSE; + } + + if (!(filehandle->fileaccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_ALL))) { + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fd %d doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, ((MonoFDHandle*) filehandle)->fd, filehandle->fileaccess); mono_w32error_set_last (ERROR_ACCESS_DENIED); + mono_fdhandle_unref ((MonoFDHandle*) filehandle); return FALSE; } @@ -5010,33 +4646,35 @@ UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 le offset = ((gint64)offset_high << 32) | offset_low; length = ((gint64)length_high << 32) | length_low; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, - handle, (gint64) offset, (gint64) length); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking fd %d, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #else offset = offset_low; length = length_low; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, handle, (gint64) offset, (gint64) length); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking fd %p, offset %" G_GINT64_FORMAT ", length %" G_GINT64_FORMAT, __func__, ((MonoFDHandle*) filehandle)->fd, (gint64) offset, (gint64) length); #endif - return _wapi_unlock_file_region (GPOINTER_TO_UINT(handle), offset, length); + ret = _wapi_unlock_file_region (((MonoFDHandle*) filehandle)->fd, offset, length); + + mono_fdhandle_unref ((MonoFDHandle*) filehandle); + return ret; } void mono_w32file_init (void) { - mono_coop_mutex_init (&stdhandle_mutex); - mono_coop_mutex_init (&file_share_mutex); + MonoFDHandleCallback file_data_callbacks = { + .close = file_data_close, + .destroy = file_data_destroy + }; + + mono_fdhandle_register (MONO_FDTYPE_FILE, &file_data_callbacks); + mono_fdhandle_register (MONO_FDTYPE_CONSOLE, &file_data_callbacks); + mono_fdhandle_register (MONO_FDTYPE_PIPE, &file_data_callbacks); - mono_w32handle_register_ops (MONO_W32HANDLE_FILE, &_wapi_file_ops); - mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops); - mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops); - mono_w32handle_register_ops (MONO_W32HANDLE_PIPE, &_wapi_pipe_ops); + mono_coop_mutex_init (&file_share_mutex); -/* mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */ -/* MONO_W32HANDLE_CAP_WAIT); */ -/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */ -/* MONO_W32HANDLE_CAP_WAIT); */ + mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops); if (g_hasenv ("MONO_STRICT_IO_EMULATION")) lock_while_writing = TRUE; diff --git a/mono/metadata/w32file.c b/mono/metadata/w32file.c index 296a84d6a47..325767f5243 100644 --- a/mono/metadata/w32file.c +++ b/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); } diff --git a/mono/metadata/w32handle.c b/mono/metadata/w32handle.c index 35a5dd93d87..98d4ace6d62 100644 --- a/mono/metadata/w32handle.c +++ b/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) { diff --git a/mono/metadata/w32handle.h b/mono/metadata/w32handle.h index b7df9a8810e..24d547952f7 100644 --- a/mono/metadata/w32handle.h +++ b/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); diff --git a/mono/metadata/w32process-unix.c b/mono/metadata/w32process-unix.c index 57340e9ed5a..280c3a9213d 100644 --- a/mono/metadata/w32process-unix.c +++ b/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 diff --git a/mono/metadata/w32socket-internals.h b/mono/metadata/w32socket-internals.h index 5122fdf5ed1..cf9fb28e466 100644 --- a/mono/metadata/w32socket-internals.h +++ b/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__ diff --git a/mono/metadata/w32socket-unix.c b/mono/metadata/w32socket-unix.c index 5816b142b05..bc1b5ccd818 100644 --- a/mono/metadata/w32socket-unix.c +++ b/mono/metadata/w32socket-unix.c @@ -51,180 +51,163 @@ #include "w32socket.h" #include "w32socket-internals.h" #include "w32error.h" -#include "w32handle.h" +#include "fdhandle.h" #include "utils/mono-logger-internals.h" #include "utils/mono-poll.h" typedef struct { - int domain; - int type; - int protocol; - int saved_error; - int still_readable; -} MonoW32HandleSocket; + MonoFDHandle fdhandle; + gint domain; + gint type; + gint protocol; + gint saved_error; + gint still_readable; +} SocketHandle; + +static SocketHandle* +socket_data_create (MonoFDType type, gint fd) +{ + SocketHandle *sockethandle; + + sockethandle = g_new0 (SocketHandle, 1); + mono_fdhandle_init ((MonoFDHandle*) sockethandle, type, fd); -static guint32 in_cleanup = 0; + return sockethandle; +} static void -socket_close (gpointer handle, gpointer data) +socket_data_close (MonoFDHandle *fdhandle) { - int ret; - MonoW32HandleSocket *socket_handle = (MonoW32HandleSocket *)data; - MonoThreadInfo *info = mono_thread_info_current (); + MonoThreadInfo *info; + SocketHandle* sockethandle; + gint ret; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle); + sockethandle = (SocketHandle*) fdhandle; + g_assert (sockethandle); - /* Shutdown the socket for reading, to interrupt any potential - * receives that may be blocking for data. See bug 75705. */ - shutdown (GPOINTER_TO_UINT (handle), SHUT_RD); + info = mono_thread_info_current (); - do { - ret = close (GPOINTER_TO_UINT(handle)); - } while (ret == -1 && errno == EINTR && - !mono_thread_info_is_interrupt_state (info)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing fd %d", __func__, ((MonoFDHandle*) sockethandle)->fd); + /* Shutdown the socket for reading, to interrupt any potential + * receives that may be blocking for data. See bug 75705. */ + MONO_ENTER_GC_SAFE; + shutdown (((MonoFDHandle*) sockethandle)->fd, SHUT_RD); + MONO_EXIT_GC_SAFE; + +retry_close: + MONO_ENTER_GC_SAFE; + ret = close (((MonoFDHandle*) sockethandle)->fd); + MONO_EXIT_GC_SAFE; if (ret == -1) { - gint errnum = errno; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, g_strerror (errno)); - if (!in_cleanup) - mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + if (errno == EINTR && !mono_thread_info_is_interrupt_state (info)) + goto retry_close; } - if (!in_cleanup) - socket_handle->saved_error = 0; + sockethandle->saved_error = 0; } static void -socket_details (gpointer data) +socket_data_destroy (MonoFDHandle *fdhandle) { - /* FIXME: do something */ -} + SocketHandle *sockethandle; -static const gchar* -socket_typename (void) -{ - return "Socket"; -} + sockethandle = (SocketHandle*) fdhandle; + g_assert (sockethandle); -static gsize -socket_typesize (void) -{ - return sizeof (MonoW32HandleSocket); + g_free (sockethandle); } -static MonoW32HandleOps ops = { - socket_close, /* close */ - NULL, /* signal */ - NULL, /* own */ - NULL, /* is_owned */ - NULL, /* special_wait */ - NULL, /* prewait */ - socket_details, /* details */ - socket_typename, /* typename */ - socket_typesize, /* typesize */ -}; - void mono_w32socket_initialize (void) { - mono_w32handle_register_ops (MONO_W32HANDLE_SOCKET, &ops); -} - -static gboolean -cleanup_close (gpointer handle, gpointer data, gpointer user_data) -{ - if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET) - mono_w32handle_force_close (handle, data); + MonoFDHandleCallback socket_data_callbacks = { + .close = socket_data_close, + .destroy = socket_data_destroy + }; - return FALSE; + mono_fdhandle_register (MONO_FDTYPE_SOCKET, &socket_data_callbacks); } void mono_w32socket_cleanup (void) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: cleaning up", __func__); - - in_cleanup = 1; - mono_w32handle_foreach (cleanup_close, NULL); - in_cleanup = 0; } SOCKET mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking) { - gpointer handle; - gpointer new_handle; - MonoW32HandleSocket *socket_handle; - MonoW32HandleSocket new_socket_handle; - SOCKET new_fd; + SocketHandle *sockethandle, *accepted_socket_data; MonoThreadInfo *info; + gint accepted_fd; if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { mono_w32socket_set_last_error (WSAEFAULT); return INVALID_SOCKET; } - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); return INVALID_SOCKET; } - info = mono_thread_info_current (); - - do { - new_fd = accept (sock, addr, addrlen); - } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); - - if (new_fd == -1) { - gint errnum = errno; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno)); - mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return INVALID_SOCKET; } - if (new_fd >= mono_w32handle_fd_reserve) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); - - mono_w32socket_set_last_error (WSASYSCALLFAILURE); + info = mono_thread_info_current (); - close (new_fd); + do { + MONO_ENTER_GC_SAFE; + accepted_fd = accept (((MonoFDHandle*) sockethandle)->fd, addr, addrlen); + MONO_EXIT_GC_SAFE; + } while (accepted_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); + if (accepted_fd == -1) { + gint error = mono_w32socket_convert_error (errno); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno)); + mono_w32socket_set_last_error (error); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return INVALID_SOCKET; } - new_socket_handle.domain = socket_handle->domain; - new_socket_handle.type = socket_handle->type; - new_socket_handle.protocol = socket_handle->protocol; - new_socket_handle.still_readable = 1; + accepted_socket_data = socket_data_create (MONO_FDTYPE_SOCKET, accepted_fd); + accepted_socket_data->domain = sockethandle->domain; + accepted_socket_data->type = sockethandle->type; + accepted_socket_data->protocol = sockethandle->protocol; + accepted_socket_data->still_readable = 1; - new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd, - &new_socket_handle); - if(new_handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating socket handle", __func__); - mono_w32socket_set_last_error (ERROR_GEN_FAILURE); - return INVALID_SOCKET; - } + mono_fdhandle_insert ((MonoFDHandle*) accepted_socket_data); - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with", - __func__, new_handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning accepted handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) accepted_socket_data)->fd)); - return new_fd; + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + return ((MonoFDHandle*) accepted_socket_data)->fd; } int mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking) { - gpointer handle; - MonoW32HandleSocket *socket_handle; + SocketHandle *sockethandle; + gint ret; + + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } - if (connect (sock, addr, addrlen) == -1) { + MONO_ENTER_GC_SAFE; + ret = connect (((MonoFDHandle*) sockethandle)->fd, addr, addrlen); + MONO_EXIT_GC_SAFE; + if (ret == -1) { MonoThreadInfo *info; mono_pollfd fds; gint errnum, so_error; @@ -251,29 +234,41 @@ mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, g if (errnum != WSAEWOULDBLOCK) { /* ECONNRESET means the socket was closed by another thread */ /* Async close on mac raises ECONNABORTED. */ - socket_handle->saved_error = errnum; + sockethandle->saved_error = errnum; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } info = mono_thread_info_current (); - fds.fd = sock; + fds.fd = ((MonoFDHandle*) sockethandle)->fd; fds.events = MONO_POLLOUT; - while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) { + for (;;) { + MONO_ENTER_GC_SAFE; + ret = mono_poll (&fds, 1, -1); + MONO_EXIT_GC_SAFE; + if (ret != -1 || mono_thread_info_is_interrupt_state (info)) + break; + if (errno != EINTR) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } } len = sizeof(so_error); - if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { + MONO_ENTER_GC_SAFE; + ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_ERROR, &so_error, &len); + MONO_EXIT_GC_SAFE; + if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -281,16 +276,18 @@ mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, g gint errnum = mono_w32socket_convert_error (so_error); /* Need to save this socket error */ - socket_handle->saved_error = errnum; + sockethandle->saved_error = errnum; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s", __func__, g_strerror (so_error)); mono_w32socket_set_last_error (errnum); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } @@ -303,21 +300,27 @@ mono_w32socket_recv (SOCKET sock, char *buf, int len, int flags, gboolean blocki int mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking) { - gpointer handle; - MonoW32HandleSocket *socket_handle; + SocketHandle *sockethandle; int ret; MonoThreadInfo *info; - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); do { - ret = recvfrom (sock, buf, len, flags, from, fromlen); + MONO_ENTER_GC_SAFE; + ret = recvfrom (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, from, fromlen); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == 0 && len > 0) { @@ -339,7 +342,7 @@ mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sock * still_readable != 1 then shutdown * (SHUT_RD|SHUT_RDWR) has been called locally. */ - if (socket_handle->still_readable != 1) { + if (sockethandle->still_readable != 1) { ret = -1; errno = EINTR; } @@ -349,8 +352,10 @@ mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sock gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return ret; } @@ -377,18 +382,22 @@ msghdr_iov_free (struct msghdr *hdr) int mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking) { - MonoW32HandleSocket *socket_handle; + SocketHandle *sockethandle; MonoThreadInfo *info; - gpointer handle; gint ret; struct msghdr hdr; g_assert (overlapped == NULL); g_assert (complete == NULL); - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } @@ -397,14 +406,16 @@ mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 wsabuf_to_msghdr (buffers, count, &hdr); do { - ret = recvmsg (sock, &hdr, *flags); + MONO_ENTER_GC_SAFE; + ret = recvmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, *flags); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); msghdr_iov_free (&hdr); if (ret == 0) { /* see mono_w32socket_recvfrom */ - if (socket_handle->still_readable != 1) { + if (sockethandle->still_readable != 1) { ret = -1; errno = EINTR; } @@ -414,32 +425,41 @@ mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } *received = ret; *flags = hdr.msg_flags; + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } int mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking) { - gpointer handle; + SocketHandle *sockethandle; int ret; MonoThreadInfo *info; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); do { - ret = send (sock, buf, len, flags); + MONO_ENTER_GC_SAFE; + ret = send (((MonoFDHandle*) sockethandle)->fd, buf, len, flags); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { @@ -450,42 +470,55 @@ mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocki /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on * a blocking socket. See bug #599488 */ if (errnum == EAGAIN) { - ret = fcntl (sock, F_GETFL, 0); + MONO_ENTER_GC_SAFE; + ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0); + MONO_EXIT_GC_SAFE; if (ret != -1 && (ret & O_NONBLOCK) == 0) errnum = ETIMEDOUT; } #endif /* O_NONBLOCK */ mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return ret; } int mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking) { - gpointer handle; + SocketHandle *sockethandle; int ret; MonoThreadInfo *info; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); do { - ret = sendto (sock, buf, len, flags, to, tolen); + MONO_ENTER_GC_SAFE; + ret = sendto (((MonoFDHandle*) sockethandle)->fd, buf, len, flags, to, tolen); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return ret; } @@ -494,15 +527,20 @@ mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 { struct msghdr hdr; MonoThreadInfo *info; - gpointer handle; + SocketHandle *sockethandle; gint ret; g_assert (overlapped == NULL); g_assert (complete == NULL); - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } @@ -511,7 +549,9 @@ mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 wsabuf_to_msghdr (buffers, count, &hdr); do { - ret = sendmsg (sock, &hdr, flags); + MONO_ENTER_GC_SAFE; + ret = sendmsg (((MonoFDHandle*) sockethandle)->fd, &hdr, flags); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); msghdr_iov_free (&hdr); @@ -520,10 +560,12 @@ mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } *sent = ret; + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } @@ -533,7 +575,7 @@ BOOL mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking) { MonoThreadInfo *info; - gpointer handle; + SocketHandle *sockethandle; gint file; gssize ret; #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) @@ -542,17 +584,24 @@ mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_B gchar *buffer; #endif - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); - return FALSE; + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; } /* Write the header */ if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) { - ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE); - if (ret == SOCKET_ERROR) + ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Head, buffers->HeadLength, 0, FALSE); + if (ret == SOCKET_ERROR) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return FALSE; + } } info = mono_thread_info_current (); @@ -560,35 +609,44 @@ mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_B file = GPOINTER_TO_INT (file_handle); #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) + MONO_ENTER_GC_SAFE; ret = fstat (file, &statbuf); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } do { + MONO_ENTER_GC_SAFE; #ifdef __linux__ - ret = sendfile (sock, file, NULL, statbuf.st_size); + ret = sendfile (((MonoFDHandle*) sockethandle)->fd, file, NULL, statbuf.st_size); #elif defined(DARWIN) /* TODO: header/tail could be sent in the 5th argument */ /* TODO: Might not send the entire file for non-blocking sockets */ - ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0); + ret = sendfile (file, ((MonoFDHandle*) sockethandle)->fd, 0, &statbuf.st_size, NULL, 0); #endif + MONO_EXIT_GC_SAFE; } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); #else buffer = g_malloc (SF_BUFFER_SIZE); do { do { + MONO_ENTER_GC_SAFE; ret = read (file, buffer, SF_BUFFER_SIZE); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1 || ret == 0) break; do { - ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */ + MONO_ENTER_GC_SAFE; + ret = send (((MonoFDHandle*) sockethandle)->fd, buffer, ret, 0); /* short sends? enclose this in a loop? */ + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); @@ -598,59 +656,55 @@ mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_B if (ret == -1) { gint errnum = errno; mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return FALSE; } /* Write the tail */ if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) { - ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE); - if (ret == SOCKET_ERROR) + ret = mono_w32socket_send (((MonoFDHandle*) sockethandle)->fd, buffers->Tail, buffers->TailLength, 0, FALSE); + if (ret == SOCKET_ERROR) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return FALSE; + } } if ((flags & TF_DISCONNECT) == TF_DISCONNECT) - mono_w32handle_close (handle); + mono_w32socket_close (((MonoFDHandle*) sockethandle)->fd); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return TRUE; } SOCKET mono_w32socket_socket (int domain, int type, int protocol) { - MonoW32HandleSocket socket_handle = {0}; - gpointer handle; - SOCKET sock; - - socket_handle.domain = domain; - socket_handle.type = type; - socket_handle.protocol = protocol; - socket_handle.still_readable = 1; - - sock = socket (domain, type, protocol); - if (sock == -1 && domain == AF_INET && type == SOCK_RAW && - protocol == 0) { - /* Retry with protocol == 4 (see bug #54565) */ - // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565 - socket_handle.protocol = 4; - sock = socket (AF_INET, SOCK_RAW, 4); - } + SocketHandle *sockethandle; + gint fd; + +retry_socket: + MONO_ENTER_GC_SAFE; + fd = socket (domain, type, protocol); + MONO_EXIT_GC_SAFE; + if (fd == -1) { + if (domain == AF_INET && type == SOCK_RAW && protocol == 0) { + /* Retry with protocol == 4 (see bug #54565) */ + // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565 + protocol = 4; + goto retry_socket; + } - if (sock == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return INVALID_SOCKET; } - if (sock >= mono_w32handle_fd_reserve) { - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big (%d >= %d)", - __func__, sock, mono_w32handle_fd_reserve); - - mono_w32socket_set_last_error (WSASYSCALLFAILURE); - close (sock); - - return INVALID_SOCKET; - } + sockethandle = socket_data_create(MONO_FDTYPE_SOCKET, fd); + sockethandle->domain = domain; + sockethandle->type = type; + sockethandle->protocol = protocol; + sockethandle->still_readable = 1; /* .net seems to set this by default for SOCK_STREAM, not for * SOCK_DGRAM (see bug #36322) @@ -670,111 +724,142 @@ mono_w32socket_socket (int domain, int type, int protocol) { int ret, true_ = 1; - ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_)); + MONO_ENTER_GC_SAFE; + ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_REUSEADDR, &true_, sizeof (true_)); + MONO_EXIT_GC_SAFE; if (ret == -1) { - close (sock); gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error setting SO_REUSEADDR", __func__); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + + MONO_ENTER_GC_SAFE; + close (((MonoFDHandle*) sockethandle)->fd); + MONO_EXIT_GC_SAFE; + + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return INVALID_SOCKET; } } + mono_fdhandle_insert ((MonoFDHandle*) sockethandle); - handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, sock, &socket_handle); - if (handle == INVALID_HANDLE_VALUE) { - g_warning ("%s: error creating socket handle", __func__); - mono_w32socket_set_last_error (WSASYSCALLFAILURE); - close (sock); - return INVALID_SOCKET; - } - - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, handle); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning socket handle %p", __func__, GINT_TO_POINTER(((MonoFDHandle*) sockethandle)->fd)); - return sock; + return ((MonoFDHandle*) sockethandle)->fd; } gint mono_w32socket_bind (SOCKET sock, struct sockaddr *addr, socklen_t addrlen) { - gpointer handle; + SocketHandle *sockethandle; int ret; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } - ret = bind (sock, addr, addrlen); + MONO_ENTER_GC_SAFE; + ret = bind (((MonoFDHandle*) sockethandle)->fd, addr, addrlen); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, g_strerror(errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } gint mono_w32socket_getpeername (SOCKET sock, struct sockaddr *name, socklen_t *namelen) { - gpointer handle; + SocketHandle *sockethandle; gint ret; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } - ret = getpeername (sock, name, namelen); + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + MONO_ENTER_GC_SAFE; + ret = getpeername (((MonoFDHandle*) sockethandle)->fd, name, namelen); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getpeername error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } gint mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen) { - gpointer handle; + SocketHandle *sockethandle; gint ret; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } - ret = getsockname (sock, name, namelen); + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + MONO_ENTER_GC_SAFE; + ret = getsockname (((MonoFDHandle*) sockethandle)->fd, name, namelen); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } gint mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen) { - gpointer handle; + SocketHandle *sockethandle; gint ret; struct timeval tv; gpointer tmp_val; - MonoW32HandleSocket *socket_handle; - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } @@ -785,11 +870,14 @@ mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optva *optlen = sizeof (tv); } - ret = getsockopt (sock, level, optname, tmp_val, optlen); + MONO_ENTER_GC_SAFE; + ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -801,19 +889,20 @@ mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optva if (optname == SO_ERROR) { if (*((int *)optval) != 0) { *((int *) optval) = mono_w32socket_convert_error (*((int *)optval)); - socket_handle->saved_error = *((int *)optval); + sockethandle->saved_error = *((int *)optval); } else { - *((int *)optval) = socket_handle->saved_error; + *((int *)optval) = sockethandle->saved_error; } } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } gint mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen) { - gpointer handle; + SocketHandle *sockethandle; gint ret; gpointer tmp_val; #if defined (__linux__) @@ -822,9 +911,14 @@ mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer #endif struct timeval tv; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } @@ -851,11 +945,14 @@ mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer } #endif - ret = setsockopt (sock, level, optname, tmp_val, optlen); + MONO_ENTER_GC_SAFE; + ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, level, optname, tmp_val, optlen); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -865,71 +962,94 @@ mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer int type; socklen_t type_len = sizeof (type); - if (!getsockopt (sock, level, SO_TYPE, &type, &type_len)) { - if (type == SOCK_DGRAM || type == SOCK_STREAM) - setsockopt (sock, level, SO_REUSEPORT, tmp_val, optlen); + MONO_ENTER_GC_SAFE; + ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_TYPE, &type, &type_len); + MONO_EXIT_GC_SAFE; + if (!ret) { + if (type == SOCK_DGRAM || type == SOCK_STREAM) { + MONO_ENTER_GC_SAFE; + setsockopt (((MonoFDHandle*) sockethandle)->fd, level, SO_REUSEPORT, tmp_val, optlen); + MONO_EXIT_GC_SAFE; + } } } #endif + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return ret; } gint mono_w32socket_listen (SOCKET sock, gint backlog) { - gpointer handle; + SocketHandle *sockethandle; gint ret; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } - ret = listen (sock, backlog); + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + MONO_ENTER_GC_SAFE; + ret = listen (((MonoFDHandle*) sockethandle)->fd, backlog); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } gint mono_w32socket_shutdown (SOCKET sock, gint how) { - MonoW32HandleSocket *socket_handle; - gpointer handle; + SocketHandle *sockethandle; gint ret; - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } if (how == SHUT_RD || how == SHUT_RDWR) - socket_handle->still_readable = 0; + sockethandle->still_readable = 0; - ret = shutdown (sock, how); + MONO_ENTER_GC_SAFE; + ret = shutdown (((MonoFDHandle*) sockethandle)->fd, how); + MONO_EXIT_GC_SAFE; if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return ret; } gint mono_w32socket_disconnect (SOCKET sock, gboolean reuse) { - MonoW32HandleSocket *socket_handle; - gpointer handle; + SocketHandle *sockethandle; SOCKET newsock; gint ret; @@ -939,17 +1059,25 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse) * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn) * if we really wanted to */ - handle = GUINT_TO_POINTER (sock); - if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } - newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol); + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + MONO_ENTER_GC_SAFE; + newsock = socket (sockethandle->domain, sockethandle->type, sockethandle->protocol); + MONO_EXIT_GC_SAFE; if (newsock == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -958,32 +1086,46 @@ mono_w32socket_disconnect (SOCKET sock, gboolean reuse) * should not be a race condition between the old fd being * closed and the new socket fd being copied over */ do { - ret = dup2 (newsock, sock); + MONO_ENTER_GC_SAFE; + ret = dup2 (newsock, ((MonoFDHandle*) sockethandle)->fd); + MONO_EXIT_GC_SAFE; } while (ret == -1 && errno == EAGAIN); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + MONO_ENTER_GC_SAFE; close (newsock); + MONO_EXIT_GC_SAFE; + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } static gboolean extension_disconect (SOCKET sock, OVERLAPPED *overlapped, guint32 flags, guint32 reserved) { - return mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0; + gboolean ret; + MONO_ENTER_GC_UNSAFE; + ret = mono_w32socket_disconnect (sock, flags & TF_REUSE_SOCKET) == 0; + MONO_EXIT_GC_UNSAFE; + return ret; } static gboolean extension_transmit_file (SOCKET sock, gpointer file_handle, guint32 bytes_to_write, guint32 bytes_per_send, OVERLAPPED *ol, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags) { - return mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE); + gboolean ret; + MONO_ENTER_GC_UNSAFE; + ret = mono_w32socket_transmit_file (sock, file_handle, buffers, flags, FALSE); + MONO_EXIT_GC_UNSAFE; + return ret; } static struct { @@ -998,13 +1140,18 @@ static struct { gint mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written) { - gpointer handle; + SocketHandle *sockethandle; gint ret; gchar *buffer; - handle = GUINT_TO_POINTER (sock); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } @@ -1017,18 +1164,21 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, * actually set an error here... */ mono_w32socket_set_last_error (WSAEINVAL); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } if (outputlen < sizeof(gpointer)) { /* Or here... */ mono_w32socket_set_last_error (WSAEINVAL); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } if (output == NULL) { /* Or here */ mono_w32socket_set_last_error (WSAEINVAL); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -1037,11 +1187,13 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) { memcpy (output, &extension_functions[i].func, sizeof(gpointer)); *written = sizeof(gpointer); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } } mono_w32socket_set_last_error (WSAEINVAL); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -1050,14 +1202,18 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, if (inputlen < 3 * sizeof (guint32)) { mono_w32socket_set_last_error (WSAEINVAL); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } onoff = *((guint32*) input); - ret = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32)); + MONO_ENTER_GC_SAFE; + ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32)); + MONO_EXIT_GC_SAFE; if (ret < 0) { mono_w32socket_set_last_error (mono_w32socket_convert_error (errno)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } @@ -1074,40 +1230,51 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, keepalivetime /= 1000; if (keepalivetime == 0 || rem >= 500) keepalivetime++; - ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32)); + MONO_ENTER_GC_SAFE; + ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32)); + MONO_EXIT_GC_SAFE; if (ret == 0) { rem = keepaliveinterval % 1000; keepaliveinterval /= 1000; if (keepaliveinterval == 0 || rem >= 500) keepaliveinterval++; - ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32)); + MONO_ENTER_GC_SAFE; + ret = setsockopt (((MonoFDHandle*) sockethandle)->fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32)); + MONO_EXIT_GC_SAFE; } if (ret != 0) { mono_w32socket_set_last_error (mono_w32socket_convert_error (errno)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } #endif + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL; - ret = ioctl (sock, command, buffer); + MONO_ENTER_GC_SAFE; + ret = ioctl (((MonoFDHandle*) sockethandle)->fd, command, buffer); + MONO_EXIT_GC_SAFE; if (ret == -1) { g_free (buffer); gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } if (!buffer) { *written = 0; + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } @@ -1123,42 +1290,65 @@ mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, g_free (buffer); *written = inputlen; + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } gboolean mono_w32socket_close (SOCKET sock) { - return mono_w32handle_close (GINT_TO_POINTER (sock)); + if (!mono_fdhandle_close (sock)) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + return TRUE; } gint -mono_w32socket_set_blocking (SOCKET socket, gboolean blocking) +mono_w32socket_set_blocking (SOCKET sock, gboolean blocking) { #ifdef O_NONBLOCK + SocketHandle *sockethandle; gint ret; - gpointer handle; - handle = GINT_TO_POINTER (socket); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } /* This works better than ioctl(...FIONBIO...) * on Linux (it causes connect to return * EINPROGRESS, but the ioctl doesn't seem to) */ - ret = fcntl (socket, F_GETFL, 0); - if (ret != -1) - ret = fcntl (socket, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK))); + MONO_ENTER_GC_SAFE; + ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_GETFL, 0); + MONO_EXIT_GC_SAFE; + if (ret == -1) { + gint errnum = mono_w32socket_convert_error (errno); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_GETFL) error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (errnum); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + return SOCKET_ERROR; + } + MONO_ENTER_GC_SAFE; + ret = fcntl (((MonoFDHandle*) sockethandle)->fd, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK))); + MONO_EXIT_GC_SAFE; if (ret == -1) { - gint errnum = errno; - mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno)); - mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + gint errnum = mono_w32socket_convert_error (errno); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl(F_SETFL) error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (errnum); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; #else mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED); @@ -1167,14 +1357,19 @@ mono_w32socket_set_blocking (SOCKET socket, gboolean blocking) } gint -mono_w32socket_get_available (SOCKET socket, guint64 *amount) +mono_w32socket_get_available (SOCKET sock, guint64 *amount) { + SocketHandle *sockethandle; gint ret; - gpointer handle; - handle = GINT_TO_POINTER (socket); - if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { - mono_w32socket_set_last_error (WSAENOTSOCK); + if (!mono_fdhandle_lookup_and_ref(sock, (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (WSAENOTSOCK); + return SOCKET_ERROR; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (WSAENOTSOCK); return SOCKET_ERROR; } @@ -1190,18 +1385,30 @@ mono_w32socket_get_available (SOCKET socket, guint64 *amount) // the ip buffer. socklen_t optlen = sizeof (int); - ret = getsockopt (socket, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen); + MONO_ENTER_GC_SAFE; + ret = getsockopt (((MonoFDHandle*) sockethandle)->fd, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen); + MONO_EXIT_GC_SAFE; + if (ret == -1) { + gint errnum = mono_w32socket_convert_error (errno); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno)); + mono_w32socket_set_last_error (errnum); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + return SOCKET_ERROR; + } #else - ret = ioctl (socket, FIONREAD, (gulong*) amount); -#endif - + MONO_ENTER_GC_SAFE; + ret = ioctl (((MonoFDHandle*) sockethandle)->fd, FIONREAD, (gulong*) amount); + MONO_EXIT_GC_SAFE; if (ret == -1) { - gint errnum = errno; + gint errnum = mono_w32socket_convert_error (errno); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno)); - mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); + mono_w32socket_set_last_error (errnum); + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return SOCKET_ERROR; } +#endif + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); return 0; } @@ -1348,3 +1555,23 @@ ves_icall_System_Net_Sockets_Socket_SupportPortReuse (MonoProtocolType proto, Mo return FALSE; #endif } + +gboolean +mono_w32socket_duplicate (gpointer handle, gint32 targetProcessId, gpointer *duplicate_handle) +{ + SocketHandle *sockethandle; + + if (!mono_fdhandle_lookup_and_ref (GPOINTER_TO_INT(handle), (MonoFDHandle**) &sockethandle)) { + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + if (((MonoFDHandle*) sockethandle)->type != MONO_FDTYPE_SOCKET) { + mono_fdhandle_unref ((MonoFDHandle*) sockethandle); + mono_w32error_set_last (ERROR_INVALID_HANDLE); + return FALSE; + } + + *duplicate_handle = handle; + return TRUE; +} diff --git a/mono/metadata/w32socket-win32.c b/mono/metadata/w32socket-win32.c index a3f8d410583..4f7cc8cdcf5 100644 --- a/mono/metadata/w32socket-win32.c +++ b/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; +} diff --git a/mono/metadata/w32socket.c b/mono/metadata/w32socket.c index bd802a67bb1..9c005345582 100644 --- a/mono/metadata/w32socket.c +++ b/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); diff --git a/mono/metadata/w32socket.h b/mono/metadata/w32socket.h index 1788e2175bd..9fcd2341d78 100644 --- a/mono/metadata/w32socket.h +++ b/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,