From 0687a031b14d06353b3823b2cab20d9a712ab1b2 Mon Sep 17 00:00:00 2001 From: rfm Date: Wed, 6 Jun 2012 06:51:26 +0000 Subject: [PATCH] support very large numbers of DO connections. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@35180 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 13 +++++++++++- Source/Additions/Unicode.m | 2 +- Source/NSMessagePort.m | 20 ++++++++++-------- Source/NSSocketPort.m | 41 ++++++++++++++++++++---------------- Source/unix/GSRunLoopCtxt.m | 28 +++++++++++++++++++++--- Source/win32/GSRunLoopCtxt.m | 25 ++++++++++++++++------ 6 files changed, 90 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index e3c0c64e4..078cd29a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,18 @@ +2012-06-06 Richard Frith-Macdonald + + * Source/NSSocketPort.m: + * Source/unix/GSRunLoopCtxt.m: + * Source/NSMessagePort.m: + * Source/win32/GSRunLoopCtxt.m: + Modify code for getting file descriptors to cope with an unlimited + number (allocate buffer on heap if necessary) for server processes + with very large numbers of distributed object connections. + 2012-04-30 Riccardo Mottola * Source/NSString: - Do not include malloc on OpenBSD to avoid warning (and include stdlib always). + Do not include malloc on OpenBSD to avoid warning (and include + stdlib always). 2012-04-29 Riccardo Mottola diff --git a/Source/Additions/Unicode.m b/Source/Additions/Unicode.m index 815183723..d44a2544b 100644 --- a/Source/Additions/Unicode.m +++ b/Source/Additions/Unicode.m @@ -2573,7 +2573,7 @@ GSPrivateDefaultCStringEncoding() * First handle the fallback response from nl_langinfo() ... * if we are getting the default value we can't assume that * the user has set anything up at all, so we must use the - * OpenStep/GNUstep default encopding ... latin1, even though + * OpenStep/GNUstep default encoding ... latin1, even though * the nl_langinfo() stuff would say default is ascii. */ if (strcmp(encoding, "ANSI_X3.4-1968") == 0 /* glibc */ diff --git a/Source/NSMessagePort.m b/Source/NSMessagePort.m index 6e5f94d88..e69c6a0b8 100644 --- a/Source/NSMessagePort.m +++ b/Source/NSMessagePort.m @@ -1414,6 +1414,8 @@ typedef struct { */ - (void) getFds: (NSInteger*)fds count: (NSInteger*)count { + NSInteger limit = *count; + NSInteger pos = 0; NSMapEnumerator me; void *sock; GSMessageHandle *handle; @@ -1421,19 +1423,18 @@ typedef struct { M_LOCK(myLock); - /* - * Make sure there is enough room in the provided array. - */ - NSAssert(*count > (int)NSCountMapTable(handles), - NSInternalInconsistencyException); + *count = NSCountMapTable(handles); /* * Put in our listening socket. */ - *count = 0; if (lDesc >= 0) { - fds[(*count)++] = lDesc; + *count = *count + 1; + if (pos < limit) + { + fds[pos++] = lDesc; + } } /* @@ -1444,9 +1445,10 @@ typedef struct { me = NSEnumerateMapTable(handles); while (NSNextMapEnumeratorPair(&me, &sock, (void**)&handle)) { - if (handle->recvPort == recvSelf) + if (handle->recvPort == recvSelf + && pos < limit) { - fds[(*count)++] = (int)(intptr_t)sock; + fds[pos++] = (int)(intptr_t)sock; } } NSEndMapTableEnumeration(&me); diff --git a/Source/NSSocketPort.m b/Source/NSSocketPort.m index a74344c18..4cb02cf30 100644 --- a/Source/NSSocketPort.m +++ b/Source/NSSocketPort.m @@ -1802,6 +1802,8 @@ static Class tcpPortClass; #if defined(__MINGW__) - (void) getFds: (NSInteger*)fds count: (NSInteger*)count { + NSInteger limit = *count; + NSInteger pos = 0; NSMapEnumerator me; void *event; SOCKET fd; @@ -1810,19 +1812,18 @@ static Class tcpPortClass; M_LOCK(myLock); - /* - * Make sure there is enough room in the provided array. - */ - NSAssert(*count > (int)NSCountMapTable(events), - NSInternalInconsistencyException); + *count = NSCountMapTable(events); /* * Put in our listening socket. */ - *count = 0; if (eventListener != WSA_INVALID_EVENT) { - fds[(*count)++] = (uintptr_t)eventListener; + *count++; + if (pos < limit) + { + fds[pos++] = (uintptr_t)eventListener; + } } /* @@ -1834,9 +1835,11 @@ static Class tcpPortClass; while (NSNextMapEnumeratorPair(&me, &event, (void**)&fd)) { handle = (GSTcpHandle*)NSMapGet(handles, (void*)(uintptr_t)fd); - if (handle->recvPort == recvSelf && handle->inReplyMode == NO) + if (handle->recvPort == recvSelf + && handle->inReplyMode == NO + && pos < limit) { - fds[(*count)++] = (uintptr_t)event; + fds[pos++] = (uintptr_t)event; NSDebugMLLog(@"NSPort", @"Add event %p", event); } } @@ -1846,6 +1849,8 @@ static Class tcpPortClass; #else - (void) getFds: (NSInteger*)fds count: (NSInteger*)count { + NSInteger limit = *count; + NSInteger pos = 0; NSMapEnumerator me; void *sock; GSTcpHandle *handle; @@ -1853,19 +1858,18 @@ static Class tcpPortClass; M_LOCK(myLock); - /* - * Make sure there is enough room in the provided array. - */ - NSAssert(*count > (int)NSCountMapTable(handles), - NSInternalInconsistencyException); + *count = NSCountMapTable(handles); /* * Put in our listening socket. */ - *count = 0; if (listener >= 0) { - fds[(*count)++] = listener; + *count = *count + 1; + if (pos < limit) + { + fds[pos++] = listener; + } } /* @@ -1876,9 +1880,10 @@ static Class tcpPortClass; me = NSEnumerateMapTable(handles); while (NSNextMapEnumeratorPair(&me, &sock, (void**)&handle)) { - if (handle->recvPort == recvSelf) + if (handle->recvPort == recvSelf + && pos < limit) { - fds[(*count)++] = (int)(intptr_t)sock; + fds[pos++] = (int)(intptr_t)sock; } } NSEndMapTableEnumeration(&me); diff --git a/Source/unix/GSRunLoopCtxt.m b/Source/unix/GSRunLoopCtxt.m index 939613e3b..a254c2ebe 100644 --- a/Source/unix/GSRunLoopCtxt.m +++ b/Source/unix/GSRunLoopCtxt.m @@ -27,7 +27,7 @@ #include #endif -#define FDCOUNT 128 +#define FDCOUNT 1024 #if GS_WITH_GC == 0 static SEL wRelSel; @@ -378,10 +378,20 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt) case ET_RPORT: { id port = info->receiver; + NSInteger port_fd_size = FDCOUNT; NSInteger port_fd_count = FDCOUNT; - NSInteger port_fd_array[FDCOUNT]; + NSInteger port_fd_buffer[FDCOUNT]; + NSInteger *port_fd_array = port_fd_buffer; [port getFds: port_fd_array count: &port_fd_count]; + while (port_fd_count > port_fd_size) + { + if (port_fd_array != port_fd_buffer) free(port_fd_array); + port_fd_size = port_fd_count; + port_fd_count = port_fd_size; + port_fd_array = malloc(sizeof(NSInteger)*port_fd_size); + [port getFds: port_fd_array count: &port_fd_count]; + } NSDebugMLLog(@"NSRunLoop", @"listening to %d port handles\n", port_fd_count); while (port_fd_count--) @@ -391,6 +401,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt) NSMapInsert(_rfdMap, (void*)(intptr_t)port_fd_array[port_fd_count], info); } + if (port_fd_array != port_fd_buffer) free(port_fd_array); } break; } @@ -792,10 +803,20 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt) case ET_RPORT: { id port = info->receiver; + NSInteger port_fd_size = FDCOUNT; NSInteger port_fd_count = FDCOUNT; - NSInteger port_fd_array[FDCOUNT]; + NSInteger port_fd_buffer[FDCOUNT]; + NSInteger port_fd_array = port_fd_count; [port getFds: port_fd_array count: &port_fd_count]; + while (port_fd_count > port_fd_size) + { + if (port_fd_array != port_fd_buffer) free(port_fd_array); + port_fd_size = port_fd_count; + port_fd_count = port_fd_size; + port_fd_array = malloc(sizeof(NSInteger)*port_fd_size); + [port getFds: port_fd_array count: &port_fd_count]; + } NSDebugMLLog(@"NSRunLoop", @"listening to %d port sockets", port_fd_count); while (port_fd_count--) @@ -807,6 +828,7 @@ static void setPollfd(int fd, int event, GSRunLoopCtxt *ctxt) NSMapInsert(_rfdMap, (void*)(intptr_t)port_fd_array[port_fd_count], info); } + if (port_fd_array != port_fd_buffer) free(port_fd_array); } break; diff --git a/Source/win32/GSRunLoopCtxt.m b/Source/win32/GSRunLoopCtxt.m index ba4348e47..5cc8520d6 100644 --- a/Source/win32/GSRunLoopCtxt.m +++ b/Source/win32/GSRunLoopCtxt.m @@ -17,7 +17,7 @@ #import "../GSRunLoopWatcher.h" #import "../GSPrivate.h" -#define FDCOUNT 128 +#define FDCOUNT 1024 #if GS_WITH_GC == 0 static SEL wRelSel; @@ -347,19 +347,30 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = case ET_RPORT: { id port = info->receiver; - NSInteger port_handle_count = FDCOUNT; - NSInteger port_handle_array[FDCOUNT]; + NSInteger port_hd_size = FDCOUNT; + NSInteger port_hd_count = FDCOUNT; + NSInteger port_hd_buffer[FDCOUNT]; + NSInteger *port_hd_array = port_hd_buffer; - [port getFds: port_handle_array count: &port_handle_count]; + [port getFds: port_hd_array count: &port_hd_count]; + while (port_hd_count > port_hd_size) + { + if (port_hd_array != port_hd_buffer) free(port_hd_array); + port_hd_size = port_hd_count; + port_hd_count = port_hd_size; + port_hd_array = malloc(sizeof(NSInteger)*port_hd_size); + [port getFds: port_hd_array count: &port_hd_count]; + } NSDebugMLLog(@"NSRunLoop", @"listening to %d port handles", - port_handle_count); - while (port_handle_count--) + port_hd_count); + while (port_hd_count--) { NSMapInsert(handleMap, - (void*)(size_t) port_handle_array[port_handle_count], + (void*)(size_t) port_hd_array[port_hd_count], info); num_handles++; } + if (port_hd_array != port_hd_buffer) free(port_hd_array); } break; case ET_WINMSG: