[squeak-dev] The Trunk: Network-ul.152.mcz

commits at source.squeak.org commits at source.squeak.org
Fri Aug 15 02:48:37 UTC 2014


Levente Uzonyi uploaded a new version of Network to project The Trunk:
http://source.squeak.org/trunk/Network-ul.152.mcz

==================== Summary ====================

Name: Network-ul.152
Author: ul
Time: 15 August 2014, 4:25:21.446 am
UUID: 3af235fb-434f-4941-a044-fd0d71c5d46f
Ancestors: Network-nice.151

Patched all methods of Socket which wait for the readSemaphore the same way #waitForDataIfClosed: was patched.
Created a new preference for the maximum timeout, because in some real-time applications it's better to use less than 500ms.
This fixes some random long waits/unexpected behavior for the users of SocketStream (e.g. WebClient, RFB, etc).

=============== Diff against Network-nice.151 ===============

Item was changed:
  Object subclass: #Socket
  	instanceVariableNames: 'semaphore socketHandle readSemaphore writeSemaphore'
+ 	classVariableNames: 'Connected DeadServer InvalidSocket MaximumReadSemaphoreWaitTimeout OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'
- 	classVariableNames: 'Connected DeadServer InvalidSocket OtherEndClosed Registry RegistryThreshold TCPSocketType ThisEndClosed UDPSocketType Unconnected WaitingForConnection'
  	poolDictionaries: ''
  	category: 'Network-Kernel'!
  
  !Socket commentStamp: 'gk 12/13/2005 00:43' prior: 0!
  A Socket represents a network connection point. Current sockets are designed to support the TCP/IP and UDP protocols. Sockets are the lowest level of networking object in Squeak and are not normally used directly. SocketStream is a higher level object wrapping a Socket in a stream like protocol.
  
  ProtocolClient and subclasses are in turn wrappers around a SocketStream to provide support for specific network protocols such as POP, NNTP, HTTP, and FTP.!

Item was added:
+ ----- Method: Socket class>>maximumReadSemaphoreWaitTimeout (in category 'preferences') -----
+ maximumReadSemaphoreWaitTimeout
+ 
+ 	<preference: 'Maximum readSemaphore wait timeout.'
+ 	category: 'general'
+ 	description: 'The number of milliseconds for which we''ll wait for the readSemaphore of a Socket to signal. This is used by a workaround for a VM bug. Lower values use more CPU, but result in less delay in extremal cases.'
+ 	type: #Number>
+ 	^MaximumReadSemaphoreWaitTimeout ifNil: [ 500 ]!

Item was added:
+ ----- Method: Socket class>>maximumReadSemaphoreWaitTimeout: (in category 'preferences') -----
+ maximumReadSemaphoreWaitTimeout: anInteger
+ 	"The number of milliseconds for which we'll wait for the readSemaphore to signal. This is used by a workaround for a VM bug."
+ 
+ 	MaximumReadSemaphoreWaitTimeout := anInteger!

Item was changed:
  ----- Method: Socket>>waitForDataFor:ifClosed:ifTimedOut: (in category 'waiting') -----
  waitForDataFor: timeout ifClosed: closedBlock ifTimedOut: timedOutBlock
  	"Wait for the given nr of seconds for data to arrive."
  	
  	| startTime msecsDelta |
  	startTime := Time millisecondClockValue.
  	msecsDelta := (timeout * 1000) truncated.
  	[(Time millisecondsSince: startTime) < msecsDelta] whileTrue: [
  		(self primSocketReceiveDataAvailable: socketHandle)
  			ifTrue: [^self].
  		self isConnected
  			ifFalse: [^closedBlock value].
+ 		"Providing a maximum for the time for waiting is a workaround for a VM bug which causes sockets waiting for data forever in some rare cases, because the semaphore doesn't get signaled. Remove the ""min: self class maximumReadSemaphoreWaitTimeout"" part when the bug is fixed."
  		self readSemaphore waitTimeoutMSecs: 
+ 			((msecsDelta - (Time millisecondsSince: startTime) max: 0) min: self class maximumReadSemaphoreWaitTimeout).
- 			(msecsDelta - (Time millisecondsSince: startTime) max: 0).
  	].
  
  	(self primSocketReceiveDataAvailable: socketHandle)
  		ifFalse: [
  			self isConnected
  				ifTrue: [^timedOutBlock value]
  				ifFalse: [^closedBlock value]].!

Item was changed:
  ----- Method: Socket>>waitForDataIfClosed: (in category 'waiting') -----
  waitForDataIfClosed: closedBlock
  	"Wait indefinitely for data to arrive.  This method will block until
  	data is available or the socket is closed."
  
  	[
  		(self primSocketReceiveDataAvailable: socketHandle)
  			ifTrue: [^self].
  		self isConnected
  			ifFalse: [^closedBlock value].
+ 		"Providing a maximum for the time for waiting is a workaround for a VM bug which causes sockets waiting for data forever in some rare cases, because the semaphore doesn't get signaled. Replace the ""waitTimeoutMSecs: self class maximumReadSemaphoreWaitTimeout"" part with ""wait"" when the bug is fixed."
+ 		self readSemaphore waitTimeoutMSecs: self class maximumReadSemaphoreWaitTimeout ] repeat
- 		"This 500 ms waiting is a workaround for a VM bug which causes sockets waiting for data forever randomly, because the semaphore doesn't get signaled. Revert to ""self readSemaphore wait"" when the bug is fixed."
- 		self readSemaphore waitTimeoutMSecs: 500 ] repeat
  !

Item was changed:
  ----- Method: Socket>>waitForDisconnectionFor: (in category 'waiting') -----
  waitForDisconnectionFor: timeout
  	"Wait for the given nr of seconds for the connection to be broken.
  	Return true if it is broken by the deadline, false if not.
  	The client should know the connection is really going to be closed
  	(e.g., because he has called 'close' to send a close request to the other end)
  	before calling this method."
  
  	| startTime msecsDelta status |
  	startTime := Time millisecondClockValue.
  	msecsDelta := (timeout * 1000) truncated.
  	status := self primSocketConnectionStatus: socketHandle.
  	[((status == Connected) or: [(status == ThisEndClosed)]) and:
  	 [(Time millisecondsSince: startTime) < msecsDelta]] whileTrue: [
  		self discardReceivedData.
+ 		"Providing a maximum for the time for waiting is a workaround for a VM bug which causes sockets waiting for data forever in some rare cases, because the semaphore doesn't get signaled. Remove the ""min: self class maximumReadSemaphoreWaitTimeout"" part when the bug is fixed."
  		self readSemaphore waitTimeoutMSecs: 
+ 			((msecsDelta - (Time millisecondsSince: startTime) max: 0) min: self class maximumReadSemaphoreWaitTimeout).
- 			(msecsDelta - (Time millisecondsSince: startTime) max: 0).
  		status := self primSocketConnectionStatus: socketHandle].
  	^ status ~= Connected!



More information about the Squeak-dev mailing list