diff options
author | Dick Porter <dick@acm.org> | 2004-09-06 18:35:12 +0400 |
---|---|---|
committer | Dick Porter <dick@acm.org> | 2004-09-06 18:35:12 +0400 |
commit | 8b953832a63fc29fcf872506bc7466bb66737360 (patch) | |
tree | 2303c99ddf60be11dfcc921433d65745ba9fc7d2 | |
parent | 5359b46a8d2a74f9eb4f3c9318ca7a0337e38e01 (diff) |
Merge from HEAD of the handles-as-file-descriptors work.
2004-08-19 Dick Porter <dick@ximian.com>
* handles.c (_wapi_handle_count_signalled_handles): Fix thinko
introduced with the fd offset stuff: unlock handles properly when
backing off. Fixes the monologue hang at exit.
2004-08-18 Dick Porter <dick@ximian.com>
* sockets.c:
* io.c: Check that new fds fit in the table, return error if not
* daemon.c (_wapi_daemon_main):
* handles.c (shared_init): Have all processes agree on a size for
the fd table.
2004-08-17 Dick Porter <dick@ximian.com>
* daemon.c (process_new):
* handles.c (_wapi_handle_new_internal): Cope when the space
reserved for file descriptors is larger than the shared segment
size. Fixes the crash reported when running mono under gdb on
macosx.
2004-08-16 Dick Porter <dick@ximian.com>
* sockets.c:
* io.c:
* handles-private.h (_wapi_handle_fd_offset_to_handle): Improve
error checking with passed-in file descriptors.
2004-08-11 Dick Porter <dick@ximian.com>
* sockets.c:
* io.c: Returned handle values are the file descriptor the handle
encapsulates
* handles.c:
* handles-private.h:
* daemon.c: Reserve the range of handles that can have the same
values as file descriptors. These won't be used, but the values
will be used as file, console, pipe or socket handles. The fd to
handle mapping is done internally and is invisible to users.
Fixes bug 61828.
* wapi-private.h (_WAPI_HANDLE_VERSION): Increment, because we now
reserve a chunk of handle space.
svn path=/branches/mono-1-0/mono/; revision=33409
-rw-r--r-- | mono/io-layer/ChangeLog | 47 | ||||
-rw-r--r-- | mono/io-layer/daemon.c | 3 | ||||
-rw-r--r-- | mono/io-layer/handles-private.h | 52 | ||||
-rw-r--r-- | mono/io-layer/handles.c | 142 | ||||
-rw-r--r-- | mono/io-layer/io.c | 228 | ||||
-rw-r--r-- | mono/io-layer/sockets.c | 347 | ||||
-rw-r--r-- | mono/io-layer/wapi-private.h | 3 |
7 files changed, 566 insertions, 256 deletions
diff --git a/mono/io-layer/ChangeLog b/mono/io-layer/ChangeLog index b3fbbc1a976..980b680bfc0 100644 --- a/mono/io-layer/ChangeLog +++ b/mono/io-layer/ChangeLog @@ -8,6 +8,53 @@ * daemon.c: When creating a new process's handles, check whether the shared space needs to be increased +2004-08-19 Dick Porter <dick@ximian.com> + + * handles.c (_wapi_handle_count_signalled_handles): Fix thinko + introduced with the fd offset stuff: unlock handles properly when + backing off. Fixes the monologue hang at exit. + +2004-08-18 Dick Porter <dick@ximian.com> + + * sockets.c: + * io.c: Check that new fds fit in the table, return error if not + + * daemon.c (_wapi_daemon_main): + * handles.c (shared_init): Have all processes agree on a size for + the fd table. + +2004-08-17 Dick Porter <dick@ximian.com> + + * daemon.c (process_new): + * handles.c (_wapi_handle_new_internal): Cope when the space + reserved for file descriptors is larger than the shared segment + size. Fixes the crash reported when running mono under gdb on + macosx. + +2004-08-16 Dick Porter <dick@ximian.com> + + * sockets.c: + * io.c: + * handles-private.h (_wapi_handle_fd_offset_to_handle): Improve + error checking with passed-in file descriptors. + +2004-08-11 Dick Porter <dick@ximian.com> + + * sockets.c: + * io.c: Returned handle values are the file descriptor the handle + encapsulates + + * handles.c: + * handles-private.h: + * daemon.c: Reserve the range of handles that can have the same + values as file descriptors. These won't be used, but the values + will be used as file, console, pipe or socket handles. The fd to + handle mapping is done internally and is invisible to users. + Fixes bug 61828. + + * wapi-private.h (_WAPI_HANDLE_VERSION): Increment, because we now + reserve a chunk of handle space. + 2004-07-22 Dick Porter <dick@ximian.com> * timed-thread.c: diff --git a/mono/io-layer/daemon.c b/mono/io-layer/daemon.c index a2b124bc510..e2eca91b3eb 100644 --- a/mono/io-layer/daemon.c +++ b/mono/io-layer/daemon.c @@ -1498,6 +1498,9 @@ void _wapi_daemon_main(gpointer data, gpointer scratch) /* Note that we've got the starting segment already */ _wapi_shared_data[0]->num_segments=1; _wapi_shm_mapped_segments=1; + + _wapi_fd_offset_table_size=getdtablesize (); + _wapi_shared_data[0]->fd_offset_table_size = _wapi_fd_offset_table_size; startup (); diff --git a/mono/io-layer/handles-private.h b/mono/io-layer/handles-private.h index 674e01384b9..36890a97160 100644 --- a/mono/io-layer/handles-private.h +++ b/mono/io-layer/handles-private.h @@ -28,6 +28,9 @@ extern struct _WapiHandlePrivate_list **_wapi_private_data; extern pthread_mutex_t _wapi_shared_mutex; extern guint32 _wapi_shm_mapped_segments; +extern guint32 _wapi_fd_offset_table_size; +extern gpointer *_wapi_fd_offset_table; + extern guint32 _wapi_handle_new_internal (WapiHandleType type); extern gpointer _wapi_handle_new (WapiHandleType type); extern gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, @@ -93,6 +96,43 @@ extern gboolean _wapi_handle_get_or_set_share (dev_t device, ino_t inode, extern void _wapi_handle_set_share (dev_t device, ino_t inode, guint32 sharemode, guint32 access); +static inline void _wapi_handle_fd_offset_store (int fd, gpointer handle) +{ + g_assert (fd < _wapi_fd_offset_table_size); + g_assert (_wapi_fd_offset_table[fd]==NULL || handle==NULL); + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size || handle==NULL); + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Assigning fd offset %d to %p", fd, + handle); +#endif + + _wapi_fd_offset_table[fd]=handle; +} + +static inline gpointer _wapi_handle_fd_offset_to_handle (gpointer fd_handle) +{ + int fd = GPOINTER_TO_INT (fd_handle); + gpointer handle; + + if (fd >= _wapi_fd_offset_table_size) { + return(NULL); + } + + handle = _wapi_fd_offset_table[fd]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + return(NULL); + } + +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": Returning fd offset %d of %p", fd, + handle); +#endif + + return(handle); +} + static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment) { struct _WapiHandleShared_list *shared; @@ -225,6 +265,10 @@ static inline WapiHandleType _wapi_handle_type (gpointer handle) guint32 idx; guint32 segment; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); if(segment>=_wapi_shm_mapped_segments) @@ -242,6 +286,8 @@ static inline void _wapi_handle_set_signal_state (gpointer handle, struct _WapiHandleShared *shared_handle; int thr_ret; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx]; @@ -317,6 +363,8 @@ static inline gboolean _wapi_handle_issignalled (gpointer handle) guint32 idx; guint32 segment; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); return(_wapi_handle_get_shared_segment (segment)->handles[idx].signalled); @@ -352,6 +400,8 @@ static inline int _wapi_handle_lock_handle (gpointer handle) guint32 idx; guint32 segment; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle); #endif @@ -369,6 +419,8 @@ static inline int _wapi_handle_unlock_handle (gpointer handle) guint32 segment; int ret; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle); #endif diff --git a/mono/io-layer/handles.c b/mono/io-layer/handles.c index 07fc8a31f9c..a1c3dde13ef 100644 --- a/mono/io-layer/handles.c +++ b/mono/io-layer/handles.c @@ -77,6 +77,9 @@ pthread_mutex_t _wapi_shared_mutex=PTHREAD_MUTEX_INITIALIZER; */ guint32 _wapi_shm_mapped_segments; +guint32 _wapi_fd_offset_table_size; +gpointer *_wapi_fd_offset_table=NULL; + static void shared_init (void) { struct sockaddr_un shared_socket_address; @@ -86,7 +89,7 @@ static void shared_init (void) _wapi_shared_data=g_new0 (struct _WapiHandleShared_list *, 1); _wapi_private_data=g_new0 (struct _WapiHandlePrivate_list *, 1); - + attach_again: #ifndef DISABLE_SHARED_HANDLES @@ -146,6 +149,9 @@ attach_again: goto attach_again; } + } else { + _wapi_fd_offset_table_size = _wapi_shared_data[0]->fd_offset_table_size; + _wapi_fd_offset_table=g_new0 (gpointer, _wapi_fd_offset_table_size); } } @@ -158,6 +164,10 @@ attach_again: _wapi_shared_data[0]->num_segments=1; _wapi_shared_scratch=g_new0 (struct _WapiHandleScratch, 1); + + _wapi_fd_offset_table_size=getdtablesize (); + _wapi_fd_offset_table=g_new0 (gpointer, + _wapi_fd_offset_table_size); } _wapi_private_data[0]=g_new0 (struct _WapiHandlePrivate_list, 1); _wapi_shm_mapped_segments=1; @@ -240,6 +250,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type) guint32 i, j; static guint32 last=1; int thr_ret; + guint32 num_segments = _wapi_handle_get_shared_segment (0)->num_segments; /* A linear scan should be fast enough. Start from the last * allocation, assuming that handles are allocated more often @@ -250,8 +261,7 @@ guint32 _wapi_handle_new_internal (WapiHandleType type) #endif again: _wapi_handle_segment (GUINT_TO_POINTER (last), &segment, &idx); - for(i=segment; i<_wapi_handle_get_shared_segment (0)->num_segments; - i++) { + for(i=segment; i < num_segments; i++) { if(i!=segment) { idx=0; } @@ -259,8 +269,20 @@ again: for(j=idx; j<_WAPI_HANDLES_PER_SEGMENT; j++) { struct _WapiHandleShared *shared; - /* Make sure we dont try and assign handle 0 */ - if (i==0 && j==0) { + /* Make sure we dont try and assign the + * handles that would clash with fds + */ + if ((i * _WAPI_HANDLES_PER_SEGMENT + j) < _wapi_fd_offset_table_size) { + i = _wapi_fd_offset_table_size / _WAPI_HANDLES_PER_SEGMENT; + j = _wapi_fd_offset_table_size - (i * _WAPI_HANDLES_PER_SEGMENT); + + if (i >= num_segments) { + /* Need to get the caller to + * add more shared segments + */ + return(0); + } + continue; } @@ -314,7 +336,7 @@ gpointer _wapi_handle_new (WapiHandleType type) int thr_ret; mono_once (&shared_init_once, shared_init); - + again: if(shared==TRUE) { new.type=WapiHandleRequestType_New; @@ -336,8 +358,7 @@ again: thr_ret = pthread_mutex_lock (&scan_mutex); g_assert (thr_ret == 0); - handle_idx=_wapi_handle_new_internal (type); - if(handle_idx==0) { + while ((handle_idx = _wapi_handle_new_internal (type)) == 0) { /* Try and get a new segment, and have another go */ segment=_wapi_handle_get_shared_segment (0)->num_segments; _wapi_handle_ensure_mapped (segment); @@ -345,7 +366,6 @@ again: if(_wapi_handle_get_shared_segment (segment)!=NULL) { /* Got a new segment */ _wapi_handle_get_shared_segment (0)->num_segments++; - handle_idx=_wapi_handle_new_internal (type); } else { /* Map failed. Just return 0 meaning * "out of handles" @@ -361,6 +381,9 @@ again: pthread_cleanup_pop (0); } + /* Make sure we left the space for fd mappings */ + g_assert (handle_idx >= _wapi_fd_offset_table_size); + if(handle_idx==0) { g_warning (G_GNUC_PRETTY_FUNCTION ": Ran out of handles!"); @@ -414,6 +437,8 @@ gboolean _wapi_lookup_handle (gpointer handle, WapiHandleType type, guint32 idx; guint32 segment; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); _wapi_handle_ensure_mapped (segment); @@ -592,6 +617,8 @@ gpointer _wapi_search_handle_namespace (WapiHandleType type, void _wapi_handle_ref (gpointer handle) { + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + if(shared==TRUE) { WapiHandleRequest req={0}; WapiHandleResponse resp={0}; @@ -628,6 +655,8 @@ void _wapi_handle_unref (gpointer handle) gboolean destroy = FALSE; int thr_ret; + g_assert (GPOINTER_TO_UINT (handle) >= _wapi_fd_offset_table_size); + _wapi_handle_segment (handle, &segment, &idx); if(shared==TRUE) { @@ -1181,6 +1210,10 @@ gboolean _wapi_handle_test_capabilities (gpointer handle, guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1198,6 +1231,10 @@ void _wapi_handle_ops_close_shared (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1212,6 +1249,10 @@ void _wapi_handle_ops_close_private (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1233,6 +1274,10 @@ void _wapi_handle_ops_signal (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1247,6 +1292,10 @@ void _wapi_handle_ops_own (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1261,6 +1310,10 @@ gboolean _wapi_handle_ops_isowned (gpointer handle) guint32 idx, segment; WapiHandleType type; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); type=_wapi_handle_get_shared_segment (segment)->handles[idx].type; @@ -1285,6 +1338,10 @@ gboolean _wapi_handle_ops_isowned (gpointer handle) */ gboolean CloseHandle(gpointer handle) { + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + if (handle == NULL) { return(FALSE); } @@ -1308,12 +1365,17 @@ gboolean _wapi_handle_count_signalled_handles (guint32 numhandles, again: for(i=0; i<numhandles; i++) { guint32 idx, segment; + gpointer handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } - _wapi_handle_segment (handles[i], &segment, &idx); + _wapi_handle_segment (handle, &segment, &idx); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": attempting to lock %p", - handles[i]); + handle); #endif ret=mono_mutex_trylock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex); @@ -1322,11 +1384,17 @@ again: struct timespec sleepytime; #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p", handles[i]); + g_message (G_GNUC_PRETTY_FUNCTION ": attempt failed for %p: %s", handle, strerror (ret)); #endif while(i--) { - _wapi_handle_segment (handles[i], &segment, &idx); + handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + + _wapi_handle_segment (handle, &segment, &idx); thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex); g_assert (thr_ret == 0); } @@ -1364,24 +1432,29 @@ again: for(i=0; i<numhandles; i++) { guint32 idx, segment; - - _wapi_handle_ref (handles[i]); + gpointer handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } - _wapi_handle_segment (handles[i], &segment, &idx); + _wapi_handle_ref (handle); + + _wapi_handle_segment (handle, &segment, &idx); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": Checking handle %p", - handles[i]); + handle); #endif - if(((_wapi_handle_test_capabilities (handles[i], WAPI_HANDLE_CAP_OWN)==TRUE) && - (_wapi_handle_ops_isowned (handles[i])==TRUE)) || + if(((_wapi_handle_test_capabilities (handle, WAPI_HANDLE_CAP_OWN)==TRUE) && + (_wapi_handle_ops_isowned (handle)==TRUE)) || (_wapi_handle_get_shared_segment (segment)->handles[idx].signalled==TRUE)) { count++; #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION - ": Handle %p signalled", handles[i]); + ": Handle %p signalled", handle); #endif if(*lowest>i) { *lowest=i; @@ -1417,18 +1490,23 @@ void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles) for(i=0; i<numhandles; i++) { guint32 idx, segment; - - _wapi_handle_segment (handles[i], &segment, &idx); + gpointer handle = handles[i]; + + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + + _wapi_handle_segment (handle, &segment, &idx); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", - handles[i]); + handle); #endif thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex); g_assert (thr_ret == 0); - _wapi_handle_unref (handles[i]); + _wapi_handle_unref (handle); } } @@ -1500,6 +1578,10 @@ int _wapi_handle_wait_signal_handle (gpointer handle) #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 guint32 idx, segment; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); return(mono_cond_wait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, @@ -1509,6 +1591,10 @@ int _wapi_handle_wait_signal_handle (gpointer handle) struct timespec fake_timeout; int ret; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); _wapi_calc_timeout (&fake_timeout, 100); @@ -1529,6 +1615,10 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle, #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 guint32 idx, segment; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); return(mono_cond_timedwait (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, @@ -1539,6 +1629,10 @@ int _wapi_handle_timedwait_signal_handle (gpointer handle, struct timespec fake_timeout; int ret; + if (GPOINTER_TO_UINT (handle) < _wapi_fd_offset_table_size) { + handle = _wapi_handle_fd_offset_to_handle (handle); + } + _wapi_handle_segment (handle, &segment, &idx); _wapi_calc_timeout (&fake_timeout, 100); diff --git a/mono/io-layer/io.c b/mono/io-layer/io.c index cdc616743fa..a7a9b2032d0 100644 --- a/mono/io-layer/io.c +++ b/mono/io-layer/io.c @@ -271,6 +271,9 @@ static void file_close_private (gpointer handle) handle, file_private_handle->fd); #endif + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (file_private_handle->fd, NULL); + close(file_private_handle->fd); } @@ -1142,6 +1145,9 @@ static void console_close_private (gpointer handle) console_private_handle->fd); #endif + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (console_private_handle->fd, NULL); + close(console_private_handle->fd); } @@ -1301,6 +1307,9 @@ static void pipe_close_private (gpointer handle) pipe_private_handle->fd); #endif + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (pipe_private_handle->fd, NULL); + close(pipe_private_handle->fd); } @@ -1619,6 +1628,19 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, return(INVALID_HANDLE_VALUE); } + if (fd >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + SetLastError (ERROR_TOO_MANY_OPEN_FILES); + + close (fd); + g_free (filename); + + return(INVALID_HANDLE_VALUE); + } + ret = fstat (fd, &statbuf); if (ret == -1) { #ifdef DEBUG @@ -1705,7 +1727,9 @@ gpointer CreateFile(const gunichar2 *name, guint32 fileaccess, close (fd); goto cleanup; } - cf_ret = handle; + + _wapi_handle_fd_offset_store (fd, handle); + cf_ret = GINT_TO_POINTER (fd); file_private_handle->fd=fd; file_private_handle->assigned=TRUE; @@ -1991,16 +2015,16 @@ gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name, } static mono_once_t stdhandle_once=MONO_ONCE_INIT; -static gpointer stdin_handle=NULL; -static gpointer stdout_handle=NULL; -static gpointer stderr_handle=NULL; +static gpointer stdin_handle=INVALID_HANDLE_VALUE; +static gpointer stdout_handle=INVALID_HANDLE_VALUE; +static gpointer stderr_handle=INVALID_HANDLE_VALUE; static gpointer stdhandle_create (int fd, const guchar *name) { struct _WapiHandle_file *file_handle; struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; - gpointer handle, ret = NULL; + gpointer handle, ret = INVALID_HANDLE_VALUE; int flags; int thr_ret; @@ -2031,7 +2055,7 @@ static gpointer stdhandle_create (int fd, const guchar *name) if(handle==_WAPI_HANDLE_INVALID) { g_warning (G_GNUC_PRETTY_FUNCTION ": error creating file handle"); - return(NULL); + return(INVALID_HANDLE_VALUE); } pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, @@ -2047,7 +2071,10 @@ static gpointer stdhandle_create (int fd, const guchar *name) ": error looking up console handle %p", handle); goto cleanup; } - ret = handle; + + /* We know this is fd 0, 1 or 2 */ + _wapi_handle_fd_offset_store (fd, handle); + ret = GINT_TO_POINTER (fd); file_private_handle->fd=fd; file_private_handle->assigned=TRUE; @@ -2117,8 +2144,13 @@ gpointer GetStdHandle(WapiStdHandle stdhandle) return(INVALID_HANDLE_VALUE); } + if (handle == INVALID_HANDLE_VALUE) { + SetLastError (ERROR_NO_MORE_FILES); + return(INVALID_HANDLE_VALUE); + } + /* Add a reference to this handle */ - _wapi_handle_ref (handle); + _wapi_handle_ref (_wapi_handle_fd_offset_to_handle (handle)); return(handle); } @@ -2150,12 +2182,21 @@ gpointer GetStdHandle(WapiStdHandle stdhandle) * read due to an attempt to read past the end of the file), %FALSE on * error. */ -gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes, +gboolean ReadFile(gpointer fd_handle, gpointer buffer, guint32 numbytes, guint32 *bytesread, WapiOverlapped *overlapped) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].readfile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2188,12 +2229,21 @@ gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes, * * Return value: %TRUE if the write succeeds, %FALSE on error. */ -gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes, +gboolean WriteFile(gpointer fd_handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, WapiOverlapped *overlapped) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].writefile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2211,11 +2261,20 @@ gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes, * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean FlushFileBuffers(gpointer handle) +gboolean FlushFileBuffers(gpointer fd_handle) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].flushfile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2232,11 +2291,20 @@ gboolean FlushFileBuffers(gpointer handle) * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean SetEndOfFile(gpointer handle) +gboolean SetEndOfFile(gpointer fd_handle) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].setendoffile==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2272,13 +2340,22 @@ gboolean SetEndOfFile(gpointer handle) * If @highmovedistance is not %NULL, the high 32 bits of the new file * pointer are stored there. On failure, %INVALID_SET_FILE_POINTER. */ -guint32 SetFilePointer(gpointer handle, gint32 movedistance, +guint32 SetFilePointer(gpointer fd_handle, gint32 movedistance, gint32 *highmovedistance, WapiSeekMethod method) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_SET_FILE_POINTER); + } + + type = _wapi_handle_type (handle); if(io_ops[type].seek==NULL) { - return(FALSE); + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_SET_FILE_POINTER); } return(io_ops[type].seek (handle, movedistance, highmovedistance, @@ -2296,11 +2373,20 @@ guint32 SetFilePointer(gpointer handle, gint32 movedistance, * %FILE_TYPE_CHAR - @handle is a character device, such as a console. * %FILE_TYPE_PIPE - @handle is a named or anonymous pipe. */ -WapiFileType GetFileType(gpointer handle) +WapiFileType GetFileType(gpointer fd_handle) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FILE_TYPE_UNKNOWN); + } + + type = _wapi_handle_type (handle); if(io_ops[type].getfiletype==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FILE_TYPE_UNKNOWN); } @@ -2323,12 +2409,21 @@ WapiFileType GetFileType(gpointer handle) * @highsize is non-%NULL then the high 32 bits of the file size are * stored here. On failure %INVALID_FILE_SIZE is returned. */ -guint32 GetFileSize(gpointer handle, guint32 *highsize) +guint32 GetFileSize(gpointer fd_handle, guint32 *highsize) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_FILE_SIZE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].getfilesize==NULL) { - return(FALSE); + SetLastError (ERROR_INVALID_HANDLE); + return(INVALID_FILE_SIZE); } return(io_ops[type].getfilesize (handle, highsize)); @@ -2359,12 +2454,21 @@ guint32 GetFileSize(gpointer handle, guint32 *highsize) * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean GetFileTime(gpointer handle, WapiFileTime *create_time, +gboolean GetFileTime(gpointer fd_handle, WapiFileTime *create_time, WapiFileTime *last_access, WapiFileTime *last_write) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].getfiletime==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -2395,13 +2499,22 @@ gboolean GetFileTime(gpointer handle, WapiFileTime *create_time, * * Return value: %TRUE on success, %FALSE otherwise. */ -gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time, +gboolean SetFileTime(gpointer fd_handle, const WapiFileTime *create_time, const WapiFileTime *last_access, const WapiFileTime *last_write) { - WapiHandleType type=_wapi_handle_type (handle); + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + WapiHandleType type; + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } + + type = _wapi_handle_type (handle); if(io_ops[type].setfiletime==NULL) { + SetLastError (ERROR_INVALID_HANDLE); return(FALSE); } @@ -3400,10 +3513,14 @@ extern gboolean SetCurrentDirectory (const gunichar2 *path) return result; } -int _wapi_file_handle_to_fd (gpointer handle) +/* When we're confident there are no more bugs in the fd->handle + * mapping, this can be replaced as a no-op: GPOINTER_TO_INT(fd_handle) == fd + */ +int _wapi_file_handle_to_fd (gpointer fd_handle) { struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); #ifdef DEBUG g_message (G_GNUC_PRETTY_FUNCTION ": looking up fd for %p", handle); @@ -3432,6 +3549,8 @@ int _wapi_file_handle_to_fd (gpointer handle) file_private_handle->fd); #endif + g_assert (file_private_handle->fd == GPOINTER_TO_INT (fd_handle)); + return(file_private_handle->fd); } @@ -3467,6 +3586,20 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, _wapi_set_last_error_from_errno (); return(FALSE); } + + if (filedes[0] >= _wapi_fd_offset_table_size || + filedes[1] >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + SetLastError (ERROR_TOO_MANY_OPEN_FILES); + + close (filedes[0]); + close (filedes[1]); + + return(FALSE); + } /* filedes[0] is open for reading, filedes[1] for writing */ @@ -3528,18 +3661,18 @@ gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe, pipe_read_private_handle->assigned=TRUE; pipe_read_handle->fileaccess=GENERIC_READ; - *readpipe=read_handle; + _wapi_handle_fd_offset_store (filedes[0], read_handle); + *readpipe=GINT_TO_POINTER (filedes[0]); pipe_write_private_handle->fd=filedes[1]; pipe_write_private_handle->assigned=TRUE; pipe_write_handle->fileaccess=GENERIC_WRITE; - *writepipe=write_handle; + _wapi_handle_fd_offset_store (filedes[1], write_handle); + *writepipe=GINT_TO_POINTER (filedes[1]); #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION - ": Returning pipe: read handle %p, write handle %p", - read_handle, write_handle); + g_message (G_GNUC_PRETTY_FUNCTION ": Returning pipe: read handle %p (fd %d), write handle %p (fd %d)", read_handle, filedes[0], write_handle, filedes[1]); #endif write_cleanup: @@ -3612,7 +3745,7 @@ guint32 GetTempPath (guint32 len, gunichar2 *buf) } gboolean -_wapi_io_add_callback (gpointer handle, +_wapi_io_add_callback (gpointer fd_handle, WapiOverlappedCB callback, guint64 flags G_GNUC_UNUSED) { @@ -3621,6 +3754,12 @@ _wapi_io_add_callback (gpointer handle, gboolean ok; int thr_ret; gboolean ret = FALSE; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, (gpointer *) &file_handle, @@ -3794,13 +3933,19 @@ static gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length) return(TRUE); } -gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, +gboolean LockFile (gpointer fd_handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high) { struct _WapiHandle_file *file_handle; struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; off_t offset, length; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, (gpointer *)&file_handle, @@ -3846,13 +3991,20 @@ gboolean LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, length)); } -gboolean UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, - guint32 length_low, guint32 length_high) +gboolean UnlockFile (gpointer fd_handle, guint32 offset_low, + guint32 offset_high, guint32 length_low, + guint32 length_high) { struct _WapiHandle_file *file_handle; struct _WapiHandlePrivate_file *file_private_handle; gboolean ok; off_t offset, length; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + + if (handle == NULL) { + SetLastError (ERROR_INVALID_HANDLE); + return(FALSE); + } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE, (gpointer *)&file_handle, diff --git a/mono/io-layer/sockets.c b/mono/io-layer/sockets.c index 3f48f02af8e..25f165763ea 100644 --- a/mono/io-layer/sockets.c +++ b/mono/io-layer/sockets.c @@ -97,6 +97,9 @@ static void socket_close_private (gpointer handle) g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle)); + /* Blank out the mapping, to make catching errors easier */ + _wapi_handle_fd_offset_store (socket_private_handle->fd, NULL); + do { ret=close(socket_private_handle->fd); } @@ -205,20 +208,27 @@ int WSAGetLastError(void) return(err); } -int closesocket(guint32 handle) +int closesocket(guint32 fd_handle) { - _wapi_handle_unref (GUINT_TO_POINTER (handle)); + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd_handle)); + + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { + WSASetLastError (WSAENOTSOCK); + return(0); + } + + _wapi_handle_unref (handle); return(0); } -guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, - socklen_t *addrlen) +guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; struct _WapiHandlePrivate_socket *new_socket_private_handle; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); gpointer new_handle; gboolean ok; - int fd; + int new_fd; int thr_ret; guint32 ret = INVALID_SOCKET; @@ -227,21 +237,18 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, return(INVALID_SOCKET); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(INVALID_SOCKET); } do { - fd=accept(socket_private_handle->fd, addr, addrlen); + new_fd=accept(fd, addr, addrlen); } - while (fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); + while (new_fd==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); - if(fd==-1) { + if(new_fd==-1) { gint errnum = errno; #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s", @@ -254,10 +261,23 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, return(INVALID_SOCKET); } + if (new_fd >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + WSASetLastError (WSASYSCALLFAILURE); + + close (new_fd); + + return(INVALID_SOCKET); + } + new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET); if(new_handle==_WAPI_HANDLE_INVALID) { g_warning (G_GNUC_PRETTY_FUNCTION ": error creating socket handle"); + WSASetLastError (ERROR_GEN_FAILURE); return(INVALID_SOCKET); } @@ -270,12 +290,15 @@ guint32 _wapi_accept(guint32 handle, struct sockaddr *addr, (gpointer *)&new_socket_private_handle); if(ok==FALSE) { g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + ": error looking up new socket handle %p", + new_handle); goto cleanup; } - ret = GPOINTER_TO_UINT (new_handle); + + _wapi_handle_fd_offset_store (new_fd, new_handle); + ret = new_fd; - new_socket_private_handle->fd=fd; + new_socket_private_handle->fd=new_fd; #ifdef DEBUG g_message(G_GNUC_PRETTY_FUNCTION @@ -291,27 +314,23 @@ cleanup: return(ret); } -int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen) +int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { WSASetLastError(WSANOTINITIALISED); return(SOCKET_ERROR); } - - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=bind(socket_private_handle->fd, my_addr, addrlen); + ret=bind(fd, my_addr, addrlen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -326,11 +345,10 @@ int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen) return(ret); } -int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, +int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, socklen_t addrlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; gint errnum; @@ -339,17 +357,14 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } do { - ret=connect(socket_private_handle->fd, serv_addr, addrlen); + ret=connect(fd, serv_addr, addrlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); @@ -361,11 +376,11 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, errnum = errno; - ret=setsockopt (socket_private_handle->fd, SOL_SOCKET, - SO_BROADCAST, &true, sizeof(true)); + ret=setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true, + sizeof(true)); if(ret==0) { do { - ret=connect (socket_private_handle->fd, serv_addr, addrlen); + ret=connect (fd, serv_addr, addrlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); } @@ -386,11 +401,9 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr, return(ret); } -int _wapi_getpeername(guint32 handle, struct sockaddr *name, - socklen_t *namelen) +int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -398,16 +411,13 @@ int _wapi_getpeername(guint32 handle, struct sockaddr *name, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=getpeername(socket_private_handle->fd, name, namelen); + ret=getpeername(fd, name, namelen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -424,11 +434,9 @@ int _wapi_getpeername(guint32 handle, struct sockaddr *name, return(ret); } -int _wapi_getsockname(guint32 handle, struct sockaddr *name, - socklen_t *namelen) +int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -436,16 +444,13 @@ int _wapi_getsockname(guint32 handle, struct sockaddr *name, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=getsockname(socket_private_handle->fd, name, namelen); + ret=getsockname(fd, name, namelen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -462,11 +467,10 @@ int _wapi_getsockname(guint32 handle, struct sockaddr *name, return(ret); } -int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval, +int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval, socklen_t *optlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -474,17 +478,13 @@ int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=getsockopt(socket_private_handle->fd, level, optname, optval, - optlen); + ret=getsockopt(fd, level, optname, optval, optlen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -501,10 +501,9 @@ int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval, return(ret); } -int _wapi_listen(guint32 handle, int backlog) +int _wapi_listen(guint32 fd, int backlog) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -512,16 +511,13 @@ int _wapi_listen(guint32 handle, int backlog) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=listen(socket_private_handle->fd, backlog); + ret=listen(fd, backlog); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -538,19 +534,18 @@ int _wapi_listen(guint32 handle, int backlog) return(0); } -int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags) +int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags) { - return(_wapi_recvfrom(handle, buf, len, recv_flags, NULL, 0)); + return(_wapi_recvfrom(fd, buf, len, recv_flags, NULL, 0)); } -int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags, +int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, struct sockaddr *from, socklen_t *fromlen) { #ifndef HAVE_MSG_NOSIGNAL void (*old_sigpipe)(int); // old SIGPIPE handler #endif - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -558,26 +553,22 @@ int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } #ifdef HAVE_MSG_NOSIGNAL do { - ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags | MSG_NOSIGNAL, from, + ret=recvfrom(fd, buf, len, recv_flags | MSG_NOSIGNAL, from, fromlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); #else old_sigpipe = signal(SIGPIPE, SIG_IGN); do { - ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags, from, - fromlen); + ret=recvfrom(fd, buf, len, recv_flags, from, fromlen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); signal(SIGPIPE, old_sigpipe); @@ -598,13 +589,12 @@ int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags, return(ret); } -int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags) +int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags) { #ifndef HAVE_MSG_NOSIGNAL void (*old_sigpipe)(int); // old SIGPIPE handler #endif - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -612,24 +602,21 @@ int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } #ifdef HAVE_MSG_NOSIGNAL do { - ret=send(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL); + ret=send(fd, msg, len, send_flags | MSG_NOSIGNAL); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); #else old_sigpipe = signal(SIGPIPE, SIG_IGN); do { - ret=send(socket_private_handle->fd, msg, len, send_flags); + ret=send(fd, msg, len, send_flags); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); signal(SIGPIPE, old_sigpipe); @@ -649,14 +636,13 @@ int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags) return(ret); } -int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags, +int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags, const struct sockaddr *to, socklen_t tolen) { #ifndef HAVE_MSG_NOSIGNAL void (*old_sigpipe)(int); // old SIGPIPE handler #endif - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -664,24 +650,21 @@ int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } #ifdef HAVE_MSG_NOSIGNAL do { - ret=sendto(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen); + ret=sendto(fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); #else old_sigpipe = signal(SIGPIPE, SIG_IGN); do { - ret=sendto(socket_private_handle->fd, msg, len, send_flags, to, tolen); + ret=sendto(fd, msg, len, send_flags, to, tolen); } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending()); signal(SIGPIPE, old_sigpipe); @@ -701,11 +684,10 @@ int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags, return(ret); } -int _wapi_setsockopt(guint32 handle, int level, int optname, +int _wapi_setsockopt(guint32 fd, int level, int optname, const void *optval, socklen_t optlen) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -713,17 +695,13 @@ int _wapi_setsockopt(guint32 handle, int level, int optname, return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=setsockopt(socket_private_handle->fd, level, optname, optval, - optlen); + ret=setsockopt(fd, level, optname, optval, optlen); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -740,10 +718,9 @@ int _wapi_setsockopt(guint32 handle, int level, int optname, return(ret); } -int _wapi_shutdown(guint32 handle, int how) +int _wapi_shutdown(guint32 fd, int how) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -751,16 +728,13 @@ int _wapi_shutdown(guint32 handle, int how) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } - ret=shutdown(socket_private_handle->fd, how); + ret=shutdown(fd, how); if(ret==-1) { gint errnum = errno; #ifdef DEBUG @@ -802,6 +776,18 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u return(INVALID_SOCKET); } + + if (fd >= _wapi_fd_offset_table_size) { +#ifdef DEBUG + g_message (G_GNUC_PRETTY_FUNCTION ": File descriptor is too big"); +#endif + + WSASetLastError (WSASYSCALLFAILURE); + close (fd); + + return(INVALID_SOCKET); + } + mono_once (&socket_ops_once, socket_ops_init); @@ -824,7 +810,9 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u ": error looking up socket handle %p", handle); goto cleanup; } - ret = GPOINTER_TO_UINT (handle); + + _wapi_handle_fd_offset_store (fd, handle); + ret = fd; socket_private_handle->fd=fd; @@ -884,13 +872,12 @@ struct hostent *_wapi_gethostbyname(const char *hostname) } int -WSAIoctl (guint32 handle, gint32 command, - gchar *input, gint i_len, - gchar *output, gint o_len, glong *written, - void *unused1, void *unused2) +WSAIoctl (guint32 fd, gint32 command, + gchar *input, gint i_len, + gchar *output, gint o_len, glong *written, + void *unused1, void *unused2) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; gchar *buffer = NULL; @@ -899,12 +886,8 @@ WSAIoctl (guint32 handle, gint32 command, return(SOCKET_ERROR); } - ok = _wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - - if (ok == FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return SOCKET_ERROR; } @@ -912,7 +895,7 @@ WSAIoctl (guint32 handle, gint32 command, if (i_len > 0) buffer = g_memdup (input, i_len); - ret = ioctl (socket_private_handle->fd, command, buffer); + ret = ioctl (fd, command, buffer); if (ret == -1) { gint errnum = errno; #ifdef DEBUG @@ -941,10 +924,9 @@ WSAIoctl (guint32 handle, gint32 command, return 0; } -int ioctlsocket(guint32 handle, gint32 command, gpointer arg) +int ioctlsocket(guint32 fd, gint32 command, gpointer arg) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); int ret; if(startup_count==0) { @@ -952,11 +934,8 @@ int ioctlsocket(guint32 handle, gint32 command, gpointer arg) return(SOCKET_ERROR); } - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(SOCKET_ERROR); } @@ -976,19 +955,19 @@ int ioctlsocket(guint32 handle, gint32 command, gpointer arg) * connect to return EINPROGRESS, but the ioctl doesn't seem to) */ if(command==FIONBIO) { - ret=fcntl(socket_private_handle->fd, F_GETFL, 0); + ret=fcntl(fd, F_GETFL, 0); if(ret!=-1) { if(*(gboolean *)arg) { ret &= ~O_NONBLOCK; } else { ret |= O_NONBLOCK; } - ret=fcntl(socket_private_handle->fd, F_SETFL, ret); + ret=fcntl(fd, F_SETFL, ret); } } else #endif /* O_NONBLOCK */ { - ret=ioctl(socket_private_handle->fd, command, arg); + ret=ioctl(fd, command, arg); } if(ret==-1) { gint errnum = errno; @@ -1036,55 +1015,43 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds, return(ret); } -void _wapi_FD_CLR(guint32 handle, fd_set *set) +void _wapi_FD_CLR(guint32 fd, fd_set *set) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return; } - FD_CLR(socket_private_handle->fd, set); + FD_CLR(fd, set); } -int _wapi_FD_ISSET(guint32 handle, fd_set *set) +int _wapi_FD_ISSET(guint32 fd, fd_set *set) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return(0); } - return(FD_ISSET(socket_private_handle->fd, set)); + return(FD_ISSET(fd, set)); } -void _wapi_FD_SET(guint32 handle, fd_set *set) +void _wapi_FD_SET(guint32 fd, fd_set *set) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; + gpointer handle = _wapi_handle_fd_offset_to_handle (GUINT_TO_POINTER (fd)); - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if(ok==FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError(WSAENOTSOCK); return; } - FD_SET(socket_private_handle->fd, set); + FD_SET(fd, set); } #ifdef USE_AIO @@ -1119,29 +1086,23 @@ async_notifier (union sigval sig) } static gboolean -do_aio_call (gboolean is_read, gpointer handle, gpointer buffer, +do_aio_call (gboolean is_read, gpointer fd_handle, gpointer buffer, guint32 numbytes, guint32 *out_bytes, gpointer ares, SocketAsyncCB callback) { - struct _WapiHandlePrivate_socket *socket_private_handle; - gboolean ok; - int fd; + gpointer handle = _wapi_handle_fd_offset_to_handle (fd_handle); + int fd = GPOINTER_TO_UINT (fd_handle); struct aiocb *aio; int result; notifier_data_t *ndata; - ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET, - NULL, (gpointer *)&socket_private_handle); - if (ok == FALSE) { - g_warning (G_GNUC_PRETTY_FUNCTION - ": error looking up socket handle 0x%x", (guint) handle); + if (handle == NULL || + _wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return FALSE; } - fd = socket_private_handle->fd; - ndata = g_new0 (notifier_data_t, 1); aio = g_new0 (struct aiocb, 1); ndata->ares = ares; diff --git a/mono/io-layer/wapi-private.h b/mono/io-layer/wapi-private.h index 59ec8defe30..92e0682288a 100644 --- a/mono/io-layer/wapi-private.h +++ b/mono/io-layer/wapi-private.h @@ -35,7 +35,7 @@ /* Increment this whenever an incompatible change is made to the * shared handle structure. */ -#define _WAPI_HANDLE_VERSION 1 +#define _WAPI_HANDLE_VERSION 3 typedef enum { WAPI_HANDLE_UNUSED=0, @@ -152,6 +152,7 @@ struct _WapiHandleShared_list { guchar daemon[MONO_SIZEOF_SUNPATH]; _wapi_daemon_status daemon_running; + guint32 fd_offset_table_size; #if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1 mono_mutex_t signal_mutex; |