Ok, let's see if we can get a grip on what is going on.
what I did was in
sqSocketCreateNetTypeSocketTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID
after the socket() call and at the check for socket value = -1, I
always fail the primitive call.
This mimics what happens when you run out of socket handles.
In this case since we never recover then it should result in a hard
failure because the socket table is full.
I put a break point in to understand where we are, and a breakpoint at
the full GC.
What I see is the first call, where we fail.
current pharo, closure based, macintosh vm 4.1.1b2
Process
557974616 Socket>initialize:family:
557974524 >newTCP:
557974308 BlockClosure>repeatWithGCIf:
557974216 >newTCP:
557974124 >newTCP
557973968 >new
557652968 >sendTest
557652876 >?
557649476 Compiler>evaluate:in:to:notifying:ifFail:logged:
557649384 ParagraphEditor>evaluateSelection
557649228 BlockClosure>on:do:
557649136 ParagraphEditor>evaluateSelection
557649024 ParagraphEditor>doIt
The second call I note the full GC hasn't happened yet, so the code is
invoking create new socket again before the GC call, which *IS* rather
pointless.
I wonder why the second call happens before the GC?
Process
557976760
Socket
>
primSocketCreateNetwork:type:receiveBufferSize:sendBufSize:semaIndex:readSemaIndex:writeSemaIndex
:
557974616 Socket>initialize:family:
557974524 >newTCP:
557974308 BlockClosure>repeatWithGCIf:
557974216 >newTCP:
557974124 >newTCP
557973968 >new
557652968 >sendTest
557652876 >?
557649476 Compiler>evaluate:in:to:notifying:ifFail:logged:
557649384 ParagraphEditor>evaluateSelection
557649228 BlockClosure>on:do:
557649136 ParagraphEditor>evaluateSelection
557649024 ParagraphEditor>doIt
then we see the full GC which has the intent of cleaning out zombies
so that those sockets can be returned to the operating system.
Process
557683240 SystemDictionary>garbageCollect
557683044 BlockClosure>repeatWithGCIf:
557682952 >newTCP:
557682860 >newTCP
557682768 >new
557652968 >sendTest
557652876 >?
557649476 Compiler>evaluate:in:to:notifying:ifFail:logged:
557649384 ParagraphEditor>evaluateSelection
557649228 BlockClosure>on:do:
557649136 ParagraphEditor>evaluateSelection
557649024 ParagraphEditor>doIt
then again
Process
556761248 Socket>initialize:family:
556719648 >newTCP:
556692112 BlockClosure>repeatWithGCIf:
556692020 >newTCP:
556691928 >newTCP
556691836 >new
556662076 >sendTest
556661984 >?
556658584 Compiler>evaluate:in:to:notifying:ifFail:logged:
556658492 ParagraphEditor>evaluateSelection
556658336 BlockClosure>on:do:
556658244 ParagraphEditor>evaluateSelection
556658132 ParagraphEditor>doIt
and again, which seems rather pointless.
Process
556763348
Socket
>
primSocketCreateNetwork:type:receiveBufferSize:sendBufSize:semaIndex:readSemaIndex:writeSemaIndex
:
556761248 Socket>initialize:family:
556719648 >newTCP:
556692112 BlockClosure>repeatWithGCIf:
556692020 >newTCP:
556691928 >newTCP
556691836 >new
556662076 >sendTest
556661984 >?
556658584 Compiler>evaluate:in:to:notifying:ifFail:logged:
5566584\92 ParagraphEditor>evaluateSelection
556658336 BlockClosure>on:do:
556658244 ParagraphEditor>evaluateSelection
556658132 ParagraphEditor>doIt
Then the walkback pops up. Obviously should the code try to make the
socket 4 times? versus say twice?
Socket>>connectNonBlockingTo:
Receiver: a Socket[destroyed]
Arguments and temporary variables:
aSocketAddress: 128.111.221.123(pulse),9(discard)
status: -1
Receiver's instance variables:
semaphore: nil
socketHandle: nil
readSemaphore: nil
writeSemaphore: nil
primitiveOnlySupportsOneSemaphore: true
Socket>>connectTo:waitForConnectionFor:
Receiver: a Socket[destroyed]
Arguments and temporary variables:
aSocketAddress: 128.111.221.123(pulse),9(discard)
timeout: 45
Receiver's instance variables:
semaphore: nil
socketHandle: nil
readSemaphore: nil
writeSemaphore: nil
primitiveOnlySupportsOneSemaphore: true
Socket>>connectTo:
Receiver: a Socket[destroyed]
Arguments and temporary variables:
aSocketAddress: 128.111.221.123(pulse),9(discard)
Receiver's instance variables:
semaphore: nil
socketHandle: nil
readSemaphore: nil
writeSemaphore: nil
primitiveOnlySupportsOneSemaphore: true
Socket>>connectTo:port:
Receiver: a Socket[destroyed]
Arguments and temporary variables:
hostAddress: 128.111.221.123(pulse),9(discard)
port: 9
Receiver's instance variables:
semaphore: nil
socketHandle: nil
readSemaphore: nil
writeSemaphore: nil
primitiveOnlySupportsOneSemaphore: true
Socket class>>sendTest
Receiver: Socket
Arguments and temporary variables:
sock: a Socket[destroyed]
bytesToSend: nil
sendBuf: nil
t: nil
serverName: 'create.ucsb.edu'
serverAddr: 128.111.221.123(pulse),9(discard)
bytesSent: #(nil)
Receiver's instance variables:
superclass: Object
methodDict: a MethodDictionary(size 137)
format: 140
instanceVariables: #('semaphore' 'socketHandle'
'readSemaphore'
'writeSemaphore...etc...
organization: ('accessing' address localAddress localPort
peerName
port primiti...etc...
subclasses: {SocksSocket . HTTPSocket . RFBSocket}
name: #Socket
classPool: a Dictionary(#Connected->2 #DeadServer-
>'update.squeakfoundation.org...etc...
sharedPools: nil
environment: Smalltalk
category: #'Network-Kernel'
traitComposition: {}
localSelectors: nil
Socket class>>DoIt
Receiver: Socket
Arguments and temporary variables:
Receiver's instance variables:
superclass: Object
methodDict: a MethodDictionary(size 137)
format: 140
instanceVariables: #('semaphore' 'socketHandle'
'readSemaphore'
'writeSemaphore...etc...
organization: ('accessing' address localAddress localPort
peerName
port primiti...etc...
subclasses: {SocksSocket . HTTPSocket . RFBSocket}
name: #Socket
classPool: a Dictionary(#Connected->2 #DeadServer-
>'update.squeakfoundation.org...etc...
sharedPools: nil
environment: Smalltalk
category: #'Network-Kernel'
traitComposition: {}
localSelectors: nil
For cross check let's look at what happens before the closure code.
pre closure work
in a pharo0.1-10211dev09.01.3.image
(gdb) call (int) printAllStacks()
Process
545073376 Socket>initialize:
545073560 [] in >newTCP
545073284 BlockContext>repeatWithGCIf:
545072904 >newTCP
545072812 >new
544992420 >sendTest
544992328 >?
544989336 Compiler>evaluate:in:to:notifying:ifFail:logged:
544989004 [] in ParagraphEditor>evaluateSelection
544988912 BlockContext>on:do:
544988664 ParagraphEditor>evaluateSelection
544988572 ParagraphEditor>doIt
again
545075672
Socket
>
primSocketCreateNetwork:type:receiveBufferSize:sendBufSize:semaIndex:readSemaIndex:writeSemaIndex
:
545073376 Socket>initialize:
545073560 [] in >newTCP
545073284 BlockContext>repeatWithGCIf:
545072904 >newTCP
545072812 >new
544992420 >sendTest
544992328 >?
544989336 Compiler>evaluate:in:to:notifying:ifFail:logged:
544989004 [] in ParagraphEditor>evaluateSelection
544988912 BlockContext>on:do:
544988664 ParagraphEditor>evaluateSelection
544988572 ParagraphEditor>doIt
fullGC happens.
Process
545024744 SystemDictionary>garbageCollect
545024440 BlockContext>repeatWithGCIf:
545024336 >newTCP
545024244 >new
544992420 >sendTest
544992328 >?
544989336 Compiler>evaluate:in:to:notifying:ifFail:logged:
544989004 [] in ParagraphEditor>evaluateSelection
544988912 BlockContext>on:do:
544988664 ParagraphEditor>evaluateSelection
544988572 ParagraphEditor>doIt
off we go again to create socket.
Process
543469672 Socket>initialize:
543447120 [] in >newTCP
543447028 BlockContext>repeatWithGCIf:
543446924 >newTCP
543446832 >new
543438208 >sendTest
543438116 >?
543435124 Compiler>evaluate:in:to:notifying:ifFail:logged:
543434792 [] in ParagraphEditor>evaluateSelection
543434700 BlockContext>on:do:
543434452 ParagraphEditor>evaluateSelection
543434360 ParagraphEditor>doIt
off we go again to create socket.
Process
543471784
Socket
>
primSocketCreateNetwork:type:receiveBufferSize:sendBufSize:semaIndex:readSemaIndex:writeSemaIndex
:
543469672 Socket>initialize:
543447120 [] in >newTCP
543447028 BlockContext>repeatWithGCIf:
543446924 >newTCP
543446832 >new
543438208 >sendTest
543438116 >?
543435124 Compiler>evaluate:in:to:notifying:ifFail:logged:
543434792 [] in ParagraphEditor>evaluateSelection
543434700 BlockContext>on:do:
543434452 ParagraphEditor>evaluateSelection
543434360 ParagraphEditor>doIt
and end up with walkback at.
Socket status must Unconnected before opening a new connection
connectNonBlockingTo: hostAddress port: port
"Initiate a connection to the given port at the given host address.
This operation will return immediately; follow it with
waitForConnectionUntil: to wait until the connection is established."
| status |
self initializeNetwork.
status := self primSocketConnectionStatus: socketHandle.
(status == Unconnected)
ifFalse: [InvalidSocketStatusException signal: 'Socket status
must
Unconnected before opening a new connection'].
=
=
=
========================================================================
John M. McIntosh <[email protected]> Twitter:
squeaker68882
Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com
=
=
=
========================================================================
_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project