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