When tracking down why my ^C handler
(signal 2 exit)
made newlisp in -http mode crash rather then exit, I found that p_exit doesn't actually exit in daemonMode, but rather it IOchannel=0 and throws (aka longjmps) an ERR_USER_RESET error. Thus, execution eventually continues at the AFTER_ERROR_ENTRY label, where fileno stubbornly objects to the IOchannel==0 by crashing. On Linux.
I'm not sure about the intention with p_exit not actually exiting in daemonMode.
Assuming there's a good reason for it, one should avoid IOchannel=0 to let the service progress as per normal. Though, then it's seriously hard to make it exit; either import my own exit or, not so gracefully, rely on (/ 0 0).
Yes, this is how it is supposed to work. The -d demon mode will only exit/close the current connection, reset newLISP by rolling back stacks and set the evaluation level to top, then listen again for a new connection (1). The top level variable environment state is kept, e.g. when setting a global (top level) variable or definition, exiting and reconnecting again, that variable or definition has the same value.
If you want the server exit for real, use -p instead of -d.
See also:
http://www.newlisp.org/downloads/newlisp_manual.html#tcpip_server
and:
http://www.newlisp.org/downloads/newlisp_manual.html#daemon
(1) Setting IOchannel=NULL is just part of the procedure to force a restart of the server after the reset(). setupServer() then reconfigures IOchannel to a valid Unix file descriptor.
ps: you also could do
(destroy (sys-info -3))
.. if you must.
Fair enough. exit is supposed to mean "exit the session" rather than "exit the program". Maybe I should read the manual sometimes ;-)
Then I suppose something needs to be done about fileno crashing on IOchannel==0, which sometimes exits the program anyhow with core dump or continues after signaling memory corruption error etc.
The destroy option is good. Though it kills via a new signal, so I'll probably go for importing the "raw" exit instead, as it really is far too easy to grumble about.
Actually, crashing only seems to happen without open connection.
Calling exit with a connection open closes the connection and doesn't crash.
But it then also stops invoking the handler (the low level signal_handler is no longer invoked). This would be because signal_handler doesn't return, which leaves the signal in blocked state. Maybe the signal setup should use sigaction rather than signal, and set up the handling with a SA_NODEFER flag, which avoids that blocking?
Thus:
1) signal handling calling exit without open connection leads to crash, and
2) signal handling calling exit with open connection makes the signal subsequently blocked.
Basically, calling exit in a signal handler for a daemon mode script is a bad idea. I suppose calling reset in a signal handler would be a problem regardless of mode.