On 29 September 2012 14:39, Denis Kudriashov <dionisiydk@gmail.com> wrote:
Hello.
I try it for latest pharo2.0 one click. Same results. I am on Windows 7.
First I register ZnServer at workspace:
server := ZnServer on: 10025. server start. server register server isRunning & server isListening.
Then save image. When I reopen image server is running. Now if I run other application at same port and try to open pharo It will closed with pharoDebug about anable to create socket. No chance to debug and fix it.
I think it is very bad behaviour because it make impossible to run my image at different computers just because another application holds socket.
There is one strange thing. When I open another ZnServer on another image both images works nice. "server isRunning & server isListening." returns true for both. And same happens if I doing it from one single image. It is possible to create two ZnServer's for same port. Only one accept requests from webbrowser for example. But when I closed it another ZnServer start accept requests. I think I just don't know something about sockets but it looks very strange to me.
About sockets: only one process in system can listen for particular socket address. Others will fail if you try to bind to it. But there's a socket option "SO_REUSEADDR" which allows you to bind to same address, i don't remember, however what exactly mechanism happens when you doing this. About image startup: during image startup, if something bad happens, it should capture a postmortem error and show you it with debugger once startup finished. But this style of error catching is enabled only for a Process which executing actual startup, not for any other [forked] processes, of course. If any of such process (like ZnServer) getting control before startup phase finished and throws the unhandled exception there, it will quit to OS. This is what you actually observing, because ZnServer lacks any exception handler in its #listenLoop : ZnSingleThreadedServer>>start "Start me. I will start listening on my port for incoming HTTP connections. If I am running, I will first stop and thus effectively restart" self stop. self log info: [ 'Starting ', self serverProcessName ]. self class default = self ifTrue: [ self register ]. process := [ [ self listenLoop ] repeat ] forkAt: Processor highIOPriority named: self serverProcessName The way how to fix that: - put an exception handler , and handle all exceptions not letting ui manager default error handler to decide what to do for you. - defer initiating/rebinding socket connections untill a system will finish startup using Smalltalk addDeferredStartupAction: [ .... ] like following: ZnServer class >> startUp: resuming "Our system startUp hook: start all servers we manage" (resuming or: [ self alwaysRestart ]) ifTrue: [ Smalltalk addDeferredStartupAction: [ self managedServers do: [ :each | each start ] ] ] like that, if image runs headless, it will still quit to OS, since nobody handling the exception(s) when server cannot bind to specified port, while if you run image headful, it will open a debugger. -- Best regards, Igor Stasenko.