@@ -182,3 +182,47 @@ def test_valid_syntax(self):
182182 )
183183 finally :
184184 fp .close ()
185+
186+ def test_premature_eof (self ):
187+ """The boot command should write an ECO marker to stdout, read the
188+ preamble from stdin, then execute it.
189+
190+ This test writes some data to STDIN and closes it then to create an
191+ EOF situation.
192+ 1. Fork child tries to read from STDIN, but stops as EOF is received.
193+ 2. Fork child crashes (trying to decompress the junk data)
194+ 3. Fork child's file descriptors (write pipes) are closed by the OS
195+ 4. Fork parent does `dup(<read pipe>, <stdin>)` and `exec(<python>)`
196+ 5. Python reads `b''` (i.e. EOF) from stdin (a closed pipe)
197+ 6. Python runs `''` (a valid script) and exits with success"""
198+
199+ proc = testlib .subprocess .Popen (
200+ args = self .args ,
201+ stdout = testlib .subprocess .PIPE ,
202+ stderr = testlib .subprocess .PIPE ,
203+ stdin = testlib .subprocess .PIPE ,
204+ )
205+
206+ # Do not send all of the data from the preamble
207+ proc .stdin .write (self .preamble [:- 128 ])
208+ proc .stdin .flush ()
209+ proc .stdin .close ()
210+ try :
211+ returncode = proc .wait (timeout = 10 )
212+ except testlib .subprocess .TimeoutExpired :
213+ proc .kill ()
214+ proc .wait (timeout = 3 )
215+ self .fail ("First stage did not handle EOF on STDIN" )
216+ try :
217+ self .assertEqual (0 , returncode )
218+ self .assertEqual (
219+ proc .stdout .read (),
220+ mitogen .parent .BootstrapProtocol .EC0_MARKER + b ("\n " ),
221+ )
222+ self .assertIn (
223+ b ("Error -5 while decompressing data" ),
224+ proc .stderr .read (),
225+ )
226+ finally :
227+ proc .stdout .close ()
228+ proc .stderr .close ()
0 commit comments