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 |
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 |
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 |
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 |
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] |
Free forum by Nabble | Edit this page |