@@ -403,14 +403,24 @@ public function execute()
403
403
stream_set_blocking ($ this ->_stdIn , false );
404
404
}
405
405
}
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.
406
411
$ 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.
411
412
while ($ running ) {
412
413
$ status = proc_get_status ($ process );
413
414
$ 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.
414
424
if ($ hasInput && $ running ) {
415
425
if ($ isInputStream ) {
416
426
$ written = stream_copy_to_stream ($ this ->_stdIn , $ pipes [0 ], 16 * 1024 , $ writtenBytes );
@@ -427,19 +437,32 @@ public function execute()
427
437
}
428
438
}
429
439
}
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
+ //
430
450
while (($ out = fgets ($ pipes [1 ])) !== false ) {
431
451
$ this ->_stdOut .= $ out ;
432
452
}
433
453
while (($ err = fgets ($ pipes [2 ])) !== false ) {
434
454
$ this ->_stdErr .= $ err ;
435
455
}
456
+
436
457
if (!$ running ) {
437
458
$ this ->_exitCode = $ status ['exitcode ' ];
438
459
fclose ($ pipes [1 ]);
439
460
fclose ($ pipes [2 ]);
440
461
proc_close ($ process );
441
462
} 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 );
443
466
}
444
467
}
445
468
} else {
0 commit comments