Eek! eek! the geek! [entries|reading|network|archive]
simont

[ userinfo | dreamwidth userinfo ]
[ archive | journal archive ]

Mon 2006-08-28 16:55
Eek! eek! the geek!

Over the past three days I've put real new features into PuTTY, which is pretty unusual these days.

A few weeks ago I discovered that the serial port on my Linux box was kaput. It may have blown up as part of this summer's general spree of all my hardware going pop, or it may have been defunct for longer than that and I just hadn't noticed; but whatever the cause, it meant I was forced to plug the serial console of my net4501 firewall into my Windows machine instead. My lack of any particularly sensible serial comms software for Windows thus caused me to develop a strong motivation for finally getting round to putting a serial-port back end into PuTTY, which has been on the wishlist for years but we've always given it relatively low priority.

The primary difficulty with this work is that Windows draws a fundamental distinction between network sockets and any other type of file handle, so it's fiddly and annoying to do the equivalent of select(1) in a way that handles both. However, with fresh supplies of motivation and energy, I hacked together a wrapper API which stores Windows HANDLE values, presents client code with a convenient means of reading and writing them, and presents front end code with a convenient means of incorporating them into its event loop. Armed with this, I was able to produce a serial back end in relatively short order.

Also, another feature which has been blocked for years on the appearance of that piece of infrastructure is local proxy support (equivalent to ProxyCommand in OpenSSH) on Windows. So I did that too, while I was at it; and I also hacked in a handy option in Plink which uses the SSH port forwarding support to do the equivalent of a server-side invocation of netcat, only without depending on any particular binary being installed server-side; this makes it useful as a fairly general-purpose local proxy command.

In the process I got cross with Windows's file I/O API. It has a thing called ‘overlapped access’, which essentially means you tell it to start doing a read or a write, and check back later to see if it's finished. If you only have one thread, this is undoubtedly really useful, but in fact I decided it was less hassle just to fork off a subthread for each direction of I/O. If I do that, I thought, I won't need the annoying ‘overlapped’ bureaucracy, because each thread can block independently of the other. Right?

Wrong. It turns out that overlapped file access is mandatory if you want to read and write the same file simultaneously (which you do if it's a serial port). If you don't use overlapped access, then a pending write causes a read on the same handle to return an error code, and vice versa. I can see no credible reason at the API level why this should be so. I can only assume that in the distant past before threads were invented, overlapped access was the only way to do simultaneous reading and writing on the same handle, and nobody in Microsoft has ever got round to digging out all the assumptions left in the code from those days. So in fact, even though each of my I/O threads would be happy just to perform a blocking read or write, they actually have to perform an overlapped read or write and then immediately call the ‘wait for overlapped result’ function in blocking mode. *sigh*

Another thing that puzzles me is that the PuTTY serial back end currently seems to lose data if the device at the other end of the serial connection is sending lots while PuTTY does not have the input focus. I can only assume Windows does something hideous to thread priorities depending on where the GUI input focus is, which is a completely horrible idea from the word go and also I have no idea how to work around it yet. Gah.

On the plus side, I also learned this weekend about ‘strings -f’, which is one of the most useful command-line options I've seen in months, and in ignorance of the existence of which I have been devising nasty ad-hockery with for and sed to do the same job every time I want to know which of a number of binary files a string is in. No more! -f will come to my rescue the next time I need rescuing.

LinkReply
[identity profile] mjg59.livejournal.comMon 2006-08-28 16:03
I can only assume Windows does something hideous to thread priorities depending on where the GUI input focus is

I believe this to be the case, yes.
Link Reply to this | Thread
[identity profile] deliberateblank.livejournal.comMon 2006-08-28 16:45
It's more that the currently active GUI thread(*) gets a small priority boost (+2 on a base priority of 7) to increase interactive performance on the basis that UI should consume very little CPU, but when it needs it, it needs it *now*. When you stop being the foreground thread, you lose that boost.

As to why that causes serial line droppage, who can say. Any modern box really ought to have enough spare oomph to deal with a serial line. You could try doing IO in a pure-IO thread and setting it's thread priority to THREAD_PRIORITY_TIME_CRITICAL (==15).

(*) Foregroundness is a property of a top-level window. If the input focus is in a particular window, then its top-level parent ought to have been automatically foregrounded at some point. Each window is attached to a particular thread by virtue of having called CreateWindow in that thread - each thread for which GUI services have been enabled by calling pretty much any USER32/GDI32 function owns a set of three layered GetMessage message queues for system/synthetic (WM_PAINT etc), input (WM_KEYDOWN) and application (WM_COMMAND) messages, which process messages for any window attached to that thread. The foreground thread is the one to which the foreground window happens to be attached, and any (well, most) keyboard/mouse messages are delivered to its input queue alone.
Link Reply to this | Parent | Thread
[personal profile] simontMon 2006-08-28 19:13
Aha, found it. It wasn't in fact thread priorities at all, so sorry for sending you off on a wild goose chase. It was actually to do with my event loop occasionally getting wedged in a way that only a Windows message would break it out of, and this didn't cause problems while the window had focus because it was scheduling itself a steady stream of WM_TIMERs for some reason or other. The event loop is now more sensible, and the problem has gone away.
Link Reply to this | Parent
[personal profile] zotzMon 2006-08-28 16:11
I remember you saying a long time ago that PuTTY was the first google hit for "putty". I noticed last week while googling an electropop band that it's now the first hit for "client" as well.
Link Reply to this | Thread
[personal profile] simontMon 2006-08-28 16:30
I just tried that and it came up ninth. Not that I doubt you: I've definitely seen Google be a bit indecisive about its result ranking from time to time. And even ninth is fairly scary...
Link Reply to this | Parent | Thread
[identity profile] hsenag.livejournal.comMon 2006-08-28 16:49
Try googling for "Simon"...
Link Reply to this | Parent
[identity profile] aquarionical.livejournal.comMon 2006-08-28 18:20
Okay, So.

http://www.google.com/search?q=client - top match, a movie. Putty 8th
http://www.google.co.uk/search?q=client - PuTTY top
http://www.google.co.uk/search?q=client&meta=cr%3DcountryUK%7CcountryGB (ie, "Pages from the UK" in the above's radio buttons - PuTTY third.

This is one of the reasons Google annoy me sometimes.
Link Reply to this | Parent
[identity profile] ewx.livejournal.comMon 2006-08-28 16:49
We ran into this annoying blocking behaviour too and had to switch to overlapped I/O. The bug had been there for years, but I was the first person to try to use the software in question in a way that caused it to matter... (Or at least, if any of our customers beat me to it, they didn't say anything about it not working that we can remember.)
Link Reply to this
[identity profile] mpinna.livejournal.comMon 2006-09-04 20:35
Sounds fantastic. So when do I get to throw minicom(1) out of the window?
Link Reply to this | Thread
[personal profile] simontMon 2006-09-04 22:55
Depends on what you're relying on it to do for you, I suppose.

The current development snapshots of PuTTY support basic serial port access, i.e. reading from the serial port and feeding the data to the terminal window, and reading keypresses and sending them to the serial port. The usual serial configuration (baud rate, stop bits, flow control etc) is supported; all the usual PuTTY terminal features are also supported. (My dad, in an impressive display of misunderstanding, spent five minutes on the phone making sure that serial-PuTTY would support scrollback as network-PuTTY does. It took him five minutes because I couldn't quite believe he could be in any doubt!)

So if that's all you asked of Minicom, you can probably chuck it out right now (or at least after ten minutes of testing). If you were also after more interesting things like zmodem file transfer, it might be a while yet; zmodem has been on the PuTTY wishlist for a long time and we've always considered it to have low priority. Though that may need to change now we do serial ports, over which it's significantly less redundant than it is over SSH sessions...
Link Reply to this | Parent
navigation
[ go | Previous Entry | Next Entry ]
[ add | to Memories ]