E.8 Single-threaded code

PuTTY and its supporting tools, or at least the vast majority of them, run in only one OS thread.

This means that if you're devising some piece of internal mechanism, there's no need to use locks to make sure it doesn't get called by two threads at once. The only way code can be called re-entrantly is by recursion.

That said, most of Windows PuTTY's network handling is triggered off Windows messages requested by WSAAsyncSelect(), so if you call MessageBox() deep within some network event handling code you should be aware that you might be re-entered if a network event comes in and is passed on to our window procedure by the MessageBox() message loop.

Also, the front ends can use multiple threads if they like. For example, the Windows front-end code spawns subthreads to deal with bidirectional blocking I/O on non-network streams such as Windows pipes. However, it keeps tight control of its auxiliary threads, and uses them only for that one purpose, as a form of select(). Pretty much all the code outside windows/handle-io.c is only ever called from the one primary thread; the others just loop round blocking on file handles, and signal the main thread (via Windows event objects) when some real work needs doing. This is not considered a portability hazard because that code is already Windows-specific and needs rewriting on other platforms.

One important consequence of this: PuTTY has only one thread in which to do everything. That ‘everything’ may include managing more than one login session (section E.3), managing multiple data channels within an SSH session, responding to GUI events even when nothing is happening on the network, and responding to network requests from the server (such as repeat key exchange) even when the program is dealing with complex user interaction such as the re-configuration dialog box. This means that almost none of the PuTTY code can safely block.