@@ -403,14 +403,24 @@ public function execute()
403403 stream_set_blocking ($ this ->_stdIn , false );
404404 }
405405 }
406+
407+ // Due to the non-blocking streams we now have to check in
408+ // a loop if the process is still running. We also need to
409+ // ensure that all the pipes are written/read alternately
410+ // until there's nothing left to write/read.
406411 $ running = true ;
407- // Due to the non-blocking streams we now have to check if
408- // the process is still running. We also need to ensure
409- // that all the pipes are written/read alternately until
410- // there's nothing left to write/read.
411412 while ($ running ) {
412413 $ status = proc_get_status ($ process );
413414 $ running = $ status ['running ' ];
415+
416+ // We first write to stdIn if we have an input. For big
417+ // inputs it will only write until the input buffer of
418+ // the command is full (the command may now wait that
419+ // we read the output buffers - see below). So we may
420+ // have to continue writing in another cycle.
421+ //
422+ // After everything is written it's safe to close the
423+ // input pipe.
414424 if ($ hasInput && $ running ) {
415425 if ($ isInputStream ) {
416426 $ written = stream_copy_to_stream ($ this ->_stdIn , $ pipes [0 ], 16 * 1024 , $ writtenBytes );
@@ -427,19 +437,32 @@ public function execute()
427437 }
428438 }
429439 }
440+
441+ // Read out the output buffers because if they are full
442+ // the command may block execution. We do this even if
443+ // $running is `false`, because there could be output
444+ // left in the buffers.
445+ //
446+ // The latter is only an assumption and needs to be
447+ // verified - but it does not hurt either and works as
448+ // expected.
449+ //
430450 while (($ out = fgets ($ pipes [1 ])) !== false ) {
431451 $ this ->_stdOut .= $ out ;
432452 }
433453 while (($ err = fgets ($ pipes [2 ])) !== false ) {
434454 $ this ->_stdErr .= $ err ;
435455 }
456+
436457 if (!$ running ) {
437458 $ this ->_exitCode = $ status ['exitcode ' ];
438459 fclose ($ pipes [1 ]);
439460 fclose ($ pipes [2 ]);
440461 proc_close ($ process );
441462 } else {
442- usleep (10000 ); // wait 10 ms
463+ // The command is still running. Let's wait some
464+ // time before we start the next cycle.
465+ usleep (10000 );
443466 }
444467 }
445468 } else {
0 commit comments