Keep locking my image using BlockingCallMonitor?

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

Keep locking my image using BlockingCallMonitor?

Tim M
Help - I keep locking my image when using a BlockingCallMonitor.

I do the following steps (very similar to the tutorial):


I run some code like the following:

serverMonitor := BlockingCallMonitor new.
        serverMonitor
                callBlock: [socketA receive];
                errorBlock:
                                [:error |
                                Transcript
                                        cr;
                                        show: 'Msg Error'].
        serverMonitor
                when: #completedWith:
                send: #receivedMessage:
                to: self.
        serverMonitor monitor

I then do:

sendSocket := Socket port: port address: InternetAddress localHost.
sendSocket connect.

I then have a Java program that I run to try and connect to the server on
the port I created.  It does something wrong - and so I get a Msg Error in
the transcript - over and over again (not sure why it keeps repeating?).
So I end my java program however the errors keep repeatedly printing out.

So I do the following:

serverMonitor terminate.
(I also tried adding a serverSocked stop. as well).

Which seems to stop the messages.

Then I go to the transcript and do Edit / Clear. After the Clear, my image
freezes.


Any tips?


(One thing I did notice was that if I use the process browser, I can terminate
the process named BlockingCallMonitor and that seems to stop my image from
hanging if I clear the Transcript.

So I guess my question is how to correctly terminate my little server programatically?).


Tim


Reply | Threaded
Open this post in threaded view
|

Re: Keep locking my image using BlockingCallMonitor?

Chris Uppal-3
Tim,

> Help - I keep locking my image when using a BlockingCallMonitor.

Does <Ctrll>+<Break> unlock it ?


> serverMonitor := BlockingCallMonitor new.
> serverMonitor
> callBlock: [socketA receive];

This seems odd.  Is socketA the ServerSocket (as the name "serverMonitor"
suggests), or a Socket created by doing a #accept on the ServerSocket ?


> errorBlock:
> [:error |
> Transcript
> cr;
> show: 'Msg Error'].

If you replaced this with

    errorBlock: [:error | Transcript display: error; cr]

then you might be able to see why you are getting repeated errors.

> serverMonitor
> when: #completedWith:
> send: #receivedMessage:
> to: self.
> serverMonitor monitor

Personally, I'd use a #completionBlock for this rather than messing with
evernts.


> I then do:
>
> sendSocket := Socket port: port address: InternetAddress localHost.
> sendSocket connect.

It's not clear why you do this, or what its relevance is, if you are just about
to try to connect from an external program.


> I then have a Java program that I run to try and connect to the server on
> the port I created.

Which port ?  And, since it seems you are going to do a #receive on some socket
or other, is the Java program expected to send STBed Smalltalk objects on that
socket ?

BTW, I would avoid using #recieve like the plague unless I was in a very
tightly controlled environment.  Decoding STBed data is inherently an unsafe
operation, so if you use it at all, then you /must/ be able to trust the
source.


> So I guess my question is how to correctly terminate my little server
> programatically?).

I would just #close the server socket.  The blocked call to #accept will then
fail, which you can recognise and allow your backgound process to die.  If you
are using a BlockingCallMonitor then I think you may have to #terminate it too.
Note that closing the ServerSocket won't close any ongoing connection that were
established using that socket.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Keep locking my image using BlockingCallMonitor?

Tim M
Chris Uppal wrote:

> Does <Ctrll>+<Break> unlock it ?

I don't think so - but will try that again as I know that Ctrl-Break is
very fiddly and sometimes you have to try a few times.

> This seems odd.  Is socketA the ServerSocket (as the name "serverMonitor"
> suggests), or a Socket created by doing a #accept on the ServerSocket ?

To clarify my example - its almost verbatim from the online help.

So prior to creating my BlockingCallMonitor I am doing:

   serverSocket := ServerSocket port: port.
   socketA := serverSocket accept.


> If you replaced this with
>
>     errorBlock: [:error | Transcript display: error; cr]
>

I managed to get a bit further, and I got my Java program to connect
(you were right about the #recieve: usage, I had to change it to
recieve bytes). So initially I was getting an STBfiler excetion,
however now I am getting a Connection closed error when my java app
closes. In both cases however it keeps cycling round and round - so I'm
not sure how I'm supposed to recover (at least from the java app
closing)


> Personally, I'd use a #completionBlock for this rather than messing with
> evernts.

Good suggestion, and in the block I can just call a method on myself to
do some procesing of the message.


> > I then do:
> >
> > sendSocket := Socket port: port address: InternetAddress localHost.
> > sendSocket connect.
>
> It's not clear why you do this, or what its relevance is, if you are just about
> to try to connect from an external program.


Actually - that was my test to see if I could connect to my little
server. That worked, and I don't do this when I try my java application
(and since removing #receive and using #receiveByteArrayPartial: I can
get both mechanisms to actually receive bytes correctly now.


> > So I guess my question is how to correctly terminate my little server
> > programatically?).
>
> I would just #close the server socket.  The blocked call to #accept will then
> fail, which you can recognise and allow your backgound process to die.  If you
> are using a BlockingCallMonitor then I think you may have to #terminate it too.
> Note that closing the ServerSocket won't close any ongoing connection that were
> established using that socket.

I think this is the bit I am getting wrong - how do I recognize the
failure? In my error block where I am outpting the error, do I do
something special in there? And can I do something to keep the server
up in the case of an error?

e.g.

serverMonitor := BlockingCallMonitor new.
        serverMonitor
                callBlock: [socketA receiveByteArrayPartial: 100];
                errorBlock:
                                [:error |
                                        Transcript
                                                cr;
                                                show: 'Msg Error: ' , error printString.
                                         self restart. <--- what do I
put here?

].


This also doesn't explain why, even when my java app hasn't shut down,
if I call another method #stop from a workspace:

stop

        socketA close.
        serverSocket close.
        serverMonitor terminate.



I still get the hanging behavior? Its like the BlockingCallMonitor
doesn't actually terminate (I've tried all the permutations of defining
stop as well).

I am wondering if there is some wierdness in here, as the docs indicate
it creates some hidden window that replaces the transcript (or
something like that) - and is this was causes the hang when I try to
clear my transcript?

And as using the process viewer to terminate that BlockingCallMonitor
process seems to  prevent the hang - maybe its something to do with how
you stop - or how you handle the error when you do stop?

Tim


Reply | Threaded
Open this post in threaded view
|

Re: Keep locking my image using BlockingCallMonitor?

Chris Uppal-3
Tim

> I think this is the bit I am getting wrong - how do I recognize the
> failure? In my error block where I am outpting the error, do I do
> something special in there? And can I do something to keep the server
> up in the case of an error?

I think it would probably be easier, at least until you know what you are
doing, to dispense with BlockingCallMonitor.  It doesn't really make things so
very much easier, and it muddies the water considerably.  In particular it has
no notion of stopping when things have gone wrong -- which (now I come to think
of it) is probably why you get those endless streams of errors.

Incidentally, although I have used BCM for a couple of small things, I would
definitely not use it in a production environment since it uses
Process>>terminate, which I believe to be inherently unsafe.

To set up a server, open a ServerSocket and then fork a loop which will do
#accept.  Maybe something like (untested):

    [| incoming |
    [[incoming := serverSocket accept]
        on: SocketError "or maybe a finer grained condition"
        do: [:err |
            "log the error"
            serverSocket close].
    incoming ifNotNil: [:it | [self handleConnection: it] fork].
    serverSocket isOpen]
        whileTrue] fork.

(ugly code, I know, but it's difficult to refactor a Usenet posting ;-)  I
don't think it makes a lot of sense to try to recover from errors in that loop,
since there isn't much that will cause an #accept to fail which is recoverable
as far as I know.

#handleConnection would have its own loop to do whatever is needed to
read/write the new incoming connection.  It would close that socket once it had
finished with it.  It might attempt to recover from errors, but I see little
need for that (network errors anyway).  Note that the server stays up as long
as the network is working and the server socket is open, even if an individual
request experiences problems.  To close down the main server just #close the
server socket.  How you handle any ongoing forked request handlers is a matter
of application design.  One sensible option is just to let them finish in their
own time.

Once you understand the above loop, it should be easy enough to look at the
original example(s) and the code for BlockingCallMonitor and see what's really
going on.

As to the image hanging, I have no real idea what could be causing that.  It
sounds as if there's a deadlock somewhere, but I don't know what could be
causing it.  I have never encountered such a problem myself with networking
code (such as the above).  You do have to be a bit careful to ensure that you
are #fork-ing process which will do blocking calls (because of the way the
input loop works), but I don't see how that could cause an actual deadlock.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Keep locking my image using BlockingCallMonitor?

Schwab,Wilhelm K
Chris, Tim,

> As to the image hanging, I have no real idea what could be causing that.  It
> sounds as if there's a deadlock somewhere, but I don't know what could be
> causing it.  I have never encountered such a problem myself with networking
> code (such as the above).  You do have to be a bit careful to ensure that you
> are #fork-ing process which will do blocking calls (because of the way the
> input loop works), but I don't see how that could cause an actual deadlock.

Long ago (in computer/Dolphin years anyway), I had problems with
#connect blocking.  I think OA fixed it, but you might check that
everything is indeed overlapped and/or asynchronous as expected.

Another thing you can do is hook into control-break to dump call stacks
(to a file) for each non-dead thread.  I have found that most useful in
deployed executables, but would probably give it a shot on a hanging
image.  Make a backup first just in case you make a mess of things =:0

Have a good one,

Bill


--
Wilhelm K. Schwab, Ph.D.
[hidden email]