mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-05-28 23:34:49 -05:00

Previously, if the testcrypt subprocess suffered any kind of crash or assertion failure during a run of the Python-based test system, the effect would be that ChildProcess.read_line() would get EOF, ignore it, and silently return the empty string. Then it would carry on doing that for the rest of the program, leading to a long string of error reports in tests that were nowhere near the code that actually caused the crash. Now ChildProcess.read_line() detects EOF and raises an exception, so that the test suite won't heedlessly carry on trying to do things once it's noticed that its subprocess has gone away. This is more fiddly than it sounds, however, because of the wrinkle that sometimes that function can be called while a Python __del__ method is asking testcrypt to free something. If that happens, the exception can't be propagated out of the __del__ (analogously to the rule that it's a really terrible idea for C++ destructors to throw). So you get an annoying warning message on standard error, and then the next command sent to testcrypt will be back in the same position. Worse still, this can also happen if testcrypt has _already_ crashed, because the __del__ methods will still run. To protect against _that_, ChildProcess caches the exception after throwing it, and then each subsequent write_line() will rethrow it. And __del__ catches and explicitly ignores the exception (to avoid the annoying warning if Python has to do the same). The combined result should be that if testcrypt crashes in normal (non-__del__) context, we should get a single exception that terminates the run cleanly without cascade failures, and whose backtrace localises the problem to the actual operation that caused the crash. If testcrypt crashes in __del__, we can't quite do that well, but we can still terminate with an exception at the next opportunity, avoiding multiple cascade failures. Also in this commit, I've got rid of the try-finally in cryptsuite.py's (trivial) main program.