BlockingCallMonitor tutorial error

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

BlockingCallMonitor tutorial error

J J-6
Hello forum,

I was going through the tutorial on sockets (very nice btw, feels so
much easier to do TCP servers in this environment then any other
language I have used) but there seems to be a problem with the last
BlockingCallMonitor tutorial.  Everything works fine until I get to the
lines:

socketA close.
socketB close.

At this point the image freezes for a minute, then it just beeps on and
on forever until I terminate the dolphin image from windows.  Any idea
what could cause this?  Here is the full code listing from the tutorial
(the only thing I change is the IP address to 127 0 0 1, since I have
no 192 168 0 1 address in use):

"Here is the code to set up the Smalltalk Server"
serverSocket := ServerSocket port: 2048.
acceptanceMonitor := BlockingCallMonitor new.
acceptanceMonitor callBlock: [serverSocket accept].
acceptanceMonitor completionBlock: [:socket |
  serverMonitor := BlockingCallMonitor new.
  serverMonitor callBlock: [Compiler evaluate: socket receive logged:
false].
  serverMonitor completionBlock: [:answer | socket send: answer].
  serverMonitor errorBlock: [:error | Sound beep. serverMonitor
terminate].
  serverMonitor monitor ].
acceptanceMonitor monitor.

"Client A"
socketA := Socket port: 2048 address: (InternetAddress ipAddress: #[192
168 0 1]).
socketA connect.
socketA send: '5 factorial'; receive. "Display it"

"Client B"
socketB := Socket port: 2048 address: (InternetAddress ipAddress: #[192
168 0 1]).
socketB connect.
socketB send: '3+4'; receive. "Display it"
socketB send: '((1 to: 10) collect: [:i | i ]) reverse'; receive.
"Display it"

"Close each client"
socketA close.
socketB close.


Reply | Threaded
Open this post in threaded view
|

Re: BlockingCallMonitor tutorial error

Chris Uppal-3
JasonJ wrote:

> "Here is the code to set up the Smalltalk Server"
> serverSocket := ServerSocket port: 2048.
> acceptanceMonitor := BlockingCallMonitor new.
> acceptanceMonitor callBlock: [serverSocket accept].
> acceptanceMonitor completionBlock: [:socket |
>   serverMonitor := BlockingCallMonitor new.
>   serverMonitor callBlock: [Compiler evaluate: socket receive logged:
> false].
>   serverMonitor completionBlock: [:answer | socket send: answer].
>   serverMonitor errorBlock: [:error | Sound beep. serverMonitor
> terminate].
>   serverMonitor monitor ].
> acceptanceMonitor monitor.

The problem here is that the variable used to hold the BlockingCallMonitor for
each incoming connection (confusingly called "serverMonitor") is a workspace
variable, rather than being local to the #completionBlock: and hence local to
each connection.  So when B connects, the record of the ongoing connection to A
is damaged since the references to "serverSocket" in the orginal monitor's
blocks will now refer to the monitor used for B's connection.  I'm not sure
exactly why that causes the unpleasant symptoms that you see, but that's what's
going wrong.  If you change the code to:

serverSocket := ServerSocket port: 2048.
serverMonitor := BlockingCallMonitor new.
serverMonitor callBlock: [serverSocket accept].
serverMonitor completionBlock: [:socket || connectionMonitor |
  connectionMonitor := BlockingCallMonitor new.
  connectionMonitor callBlock: [Compiler evaluate: socket receive logged:
false].
  connectionMonitor completionBlock: [:answer | socket send: answer].
  connectionMonitor errorBlock: [:error | Sound beep. connectionMonitor
terminate].
  connectionMonitor monitor].
serverMonitor monitor.

then it should work OK.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: BlockingCallMonitor tutorial error

J J-6
Yes, that fixed it perfectly.  Thank you very much.  I am a small talk
newbie, but I think this one I should have noticed.

Will the documentation be updated to fix errors found by users in the
next release?

Thanks,
Jason

Chris Uppal wrote:

> JasonJ wrote:
>
> > "Here is the code to set up the Smalltalk Server"
> > serverSocket := ServerSocket port: 2048.
> > acceptanceMonitor := BlockingCallMonitor new.
> > acceptanceMonitor callBlock: [serverSocket accept].
> > acceptanceMonitor completionBlock: [:socket |
> >   serverMonitor := BlockingCallMonitor new.
> >   serverMonitor callBlock: [Compiler evaluate: socket receive logged:
> > false].
> >   serverMonitor completionBlock: [:answer | socket send: answer].
> >   serverMonitor errorBlock: [:error | Sound beep. serverMonitor
> > terminate].
> >   serverMonitor monitor ].
> > acceptanceMonitor monitor.
>
> The problem here is that the variable used to hold the BlockingCallMonitor for
> each incoming connection (confusingly called "serverMonitor") is a workspace
> variable, rather than being local to the #completionBlock: and hence local to
> each connection.  So when B connects, the record of the ongoing connection to A
> is damaged since the references to "serverSocket" in the orginal monitor's
> blocks will now refer to the monitor used for B's connection.  I'm not sure
> exactly why that causes the unpleasant symptoms that you see, but that's what's
> going wrong.  If you change the code to:
>
> serverSocket := ServerSocket port: 2048.
> serverMonitor := BlockingCallMonitor new.
> serverMonitor callBlock: [serverSocket accept].
> serverMonitor completionBlock: [:socket || connectionMonitor |
>   connectionMonitor := BlockingCallMonitor new.
>   connectionMonitor callBlock: [Compiler evaluate: socket receive logged:
> false].
>   connectionMonitor completionBlock: [:answer | socket send: answer].
>   connectionMonitor errorBlock: [:error | Sound beep. connectionMonitor
> terminate].
>   connectionMonitor monitor].
> serverMonitor monitor.
>
> then it should work OK.
>
>     -- chris