Testing standard output exhaustion
While writing the latest instalment of Quality Matters I've needed to be able to demonstrate exhaustion of a process's standard output stream. Such a thing is possible, but it's a lot harder to achieve than you might think. This is the story of how I achieved it.
The problem I'm attempting to demonstrate in the column instalment is what happens when writing to the standard output stream fails. Certainly, everyone knows (or should know) that such a thing is possible. But by the same token, everyone assumes (and with some cause) that such a thing is exceedingly unlikely to ever occur in the majority of use cases.
Now, I'll reserve my observations about whether making such assumptions is a good thing or not to the column; you'll have to wait until the October issue of Overload. Regardless, in order to speak with authority on the issue I wanted to be able to replicate the condition.
I tried a number of things, none of which I had much hope of success, including:
- redirecting to a new file on a full drive - the file cannot be created
- redirecting to a read-only file - the shell spots this before the redirected process
- emulating piping to a broken pipe - seems (I didn't investigate thoroughly) that the receiving program's buffering prevents strict failure being reported back in the producer process
Finally, I realised that I'd have to resort to my first idea: writing to a file on a (very nearly) full drive.
The first problem is how to get hold of a nearly full drive. Although I build my development machines with multiple partitions, it's not always convenient to fill a local hard drive. So instead, I chose a USB memory stick drive. I used an 8GB stick, becoming directory /media/XXXXXXX
on Linux (where XXXXXXX is either an arbitrary alphanum string that I assumed to be the stick serial number) or drive J:
on Windows.
Having obtained a drive to play with, the next thing is to try and nearly fill it. The idea was to fill it except for 10-20 bytes, which would then be available for a new file redirected from the process that was to experience standard output write failure, so that I could do something like the following:
> example_program > J:\\too-small
Filling the drive was easy, using the tool crfile, which creates file of arbitrary length. The problem I had was almost filling it and leaving just a few bytes. I found that the minimum size space I could leave was 32kB.
Very quickly I realised I was being a dumbo, and forgetting about file allocation granularities. It's been a long time since I did OS theory at Uni, but of course a USB memory stick will have a minimum file allocation size!
So, rather than try and write to a new file with very few bytes remaining, I could instead create a file with nearly the last remaining 32kB on the disk
> crfile J:\\too-small 32760
and then append to it, as in:
> example_program <strong>>></strong> J:\\too-small
Now it fails to write to (and then flush) the standard output stream anything longer than 8-bytes, which is what I needed to demonstrate for the column.