There probably are more places where I should catch those and act
appropriately. At least in these places, where the websocket connection is
already closed, or being closed, anyway, the right thing to do is just to
ignore exceptions, which are generated from attempts to write to an already
closed Poco WebSocket, for instance.
Also, seems that calling LOKitDocument::destroy() (in the child process's
LOOLSession dtor) causes crashes, avoid that. The can be little need for any
cleanup as the process is about to exit anyway, and the user profile is a
temporary one that will be binned.
But actually I wonder why I thought I would need signalfd at all; wouldn't it
be enough to just loop in the undertaker thread, calling waitpid(), as long as
there are child processes? I'll try after this commit.
(Besides, I now notice that when I client disconnects, we don't close the
websocket to the child process, so it never goes away. Will fix that.)
As the child processes are pre-spawned and just hang around waiting, there is
ample time to attach one in a debugger in a controlled debugging scenario
anyway.
Otherwise it uses a timestamp with one-second granularity as seed, and thus
most of the child processes pre-spawned at start will use the same seed, which
causes breakage.
Works now for the trivial 'connect' test program. Still need to add
pre-spawning of a new child process as soon as an existing one from the pool
has been taking into use. And need to test with the actual JS client.
Set the SLEEPFORDEBUGGER environment variable to the number of seconds a child
process should sleep before calling lok_init(), so that you have time to
attach the process in a debugger.
Add a new program, loadtest, that runs a requested number of client sessions
in parallel to a loolwsd server. A client session loads one of a list of test
documents, and does some operations on it.
Move the getTokenInteger() and getTokenString() functions out from LOOLSession
into a new namespace LOOLProtocol, as they are neeeded also in the loadtest
program.
Add, also in LOOLProtocol, functions to parse some of the messages from the
server. (In general that is done in client JavaScript code, of course; only
for testing purposes needed in C++ code.)
Handle the start of a child process when needed centrally, not in each command
handler.
Also, handle unrecognized commands always already in the parent
process. (Command syntax checks still done in child process, though.)
For now, each LOOL client has a separate child process (or none at all, if it
has accessed only information found in the cache). This will obviously have to
chnage to handle collaboration. Etc.
The parent process talks the same Websocket protocol with the child
processes. When there is a child process for a client, traffic from the client
is forwarded as such to the child process and vice versa.
My comment in 1b0230e4df was misleading, even if
doing this for Unix only, if we had done it as I was first thinking, we would
have needed to pass sockets between processes. But we won't, we will instead
keep all the connections to the clients in the same master process, and pass
on the WebSocketg protocol as such to child processes. That way the child
processes can go away when idle, or crash, without the connections
breaking. Or something.
Will be needed if we want loolwsd to run on Windows. Then we will have one
process receiving the connections from WebSocket clients and sending the
accepted connection sockets to child processes thatr might be already running,
either because they have been "pre-forked", or because of a collaboration
scenario where new clients join a session working on a document.
But initially we will write this as if for Unix only, so development of this
migratory socket stuff is paused for now. (And it isn't even clear whether the
API design so far is a good idea and elegantly implementable.)
Having a 'close' would mean being able to do a new 'open', too, which
introduces unneeded complexity, at least at this stage.
Just start a fresh WebSocket connection for each document.
Use a larger buffer in the TestOutput class to handle a bit larger tiles. Too
bad that the current Poco::WebSocket::receiveFrame() takes a fixed size
buffer. (I will submit a patch to Poco for a receiveFrame() that takes a
dynamically resizable buffer and handles whatever size frame the other side
sends.)