@@ -28,6 +28,7 @@ class WindowsPipes extends AbstractPipes
2828{
2929 private $ files = array ();
3030 private $ fileHandles = array ();
31+ private $ lockHandles = array ();
3132 private $ readBytes = array (
3233 Process::STDOUT => 0 ,
3334 Process::STDERR => 0 ,
@@ -47,31 +48,33 @@ public function __construct($disableOutput, $input)
4748 Process::STDOUT => Process::OUT ,
4849 Process::STDERR => Process::ERR ,
4950 );
50- $ tmpCheck = false ;
5151 $ tmpDir = sys_get_temp_dir ();
5252 $ lastError = 'unknown reason ' ;
5353 set_error_handler (function ($ type , $ msg ) use (&$ lastError ) { $ lastError = $ msg ; });
5454 for ($ i = 0 ;; ++$ i ) {
5555 foreach ($ pipes as $ pipe => $ name ) {
5656 $ file = sprintf ('%s \\sf_proc_%02X.%s ' , $ tmpDir , $ i , $ name );
57- if (file_exists ($ file ) && !unlink ($ file )) {
58- continue 2 ;
59- }
60- $ h = fopen ($ file , 'xb ' );
61- if (!$ h ) {
62- $ error = $ lastError ;
63- if ($ tmpCheck || $ tmpCheck = unlink (tempnam (false , 'sf_check_ ' ))) {
64- continue ;
65- }
57+
58+ if (!$ h = fopen ($ file .'.lock ' , 'w ' )) {
6659 restore_error_handler ();
67- throw new RuntimeException (sprintf ('A temporary file could not be opened to write the process output: %s ' , $ error ));
60+ throw new RuntimeException (sprintf ('A temporary file could not be opened to write the process output: %s ' , $ lastError ));
6861 }
69- if (!$ h || ! $ this -> fileHandles [ $ pipe ] = fopen ( $ file , ' rb ' )) {
62+ if (!flock ( $ h , LOCK_EX | LOCK_NB )) {
7063 continue 2 ;
7164 }
72- if (isset ($ this ->files [$ pipe ])) {
73- unlink ($ this ->files [$ pipe ]);
65+ if (isset ($ this ->lockHandles [$ pipe ])) {
66+ flock ($ this ->lockHandles [$ pipe ], LOCK_UN );
67+ fclose ($ this ->lockHandles [$ pipe ]);
7468 }
69+ $ this ->lockHandles [$ pipe ] = $ h ;
70+
71+ if (!fclose (fopen ($ file , 'w ' )) || !$ h = fopen ($ file , 'r ' )) {
72+ flock ($ this ->lockHandles [$ pipe ], LOCK_UN );
73+ fclose ($ this ->lockHandles [$ pipe ]);
74+ unset($ this ->lockHandles [$ pipe ]);
75+ continue 2 ;
76+ }
77+ $ this ->fileHandles [$ pipe ] = $ h ;
7578 $ this ->files [$ pipe ] = $ file ;
7679 }
7780 break ;
@@ -85,7 +88,6 @@ public function __construct($disableOutput, $input)
8588 public function __destruct ()
8689 {
8790 $ this ->close ();
88- $ this ->removeFiles ();
8991 }
9092
9193 /**
@@ -145,8 +147,11 @@ public function readAndWrite($blocking, $close = false)
145147 $ read [$ type ] = $ data ;
146148 }
147149 if ($ close ) {
150+ ftruncate ($ fileHandle , 0 );
148151 fclose ($ fileHandle );
149- unset($ this ->fileHandles [$ type ]);
152+ flock ($ this ->lockHandles [$ type ], LOCK_UN );
153+ fclose ($ this ->lockHandles [$ type ]);
154+ unset($ this ->fileHandles [$ type ], $ this ->lockHandles [$ type ]);
150155 }
151156 }
152157
@@ -167,10 +172,13 @@ public function areOpen()
167172 public function close ()
168173 {
169174 parent ::close ();
170- foreach ($ this ->fileHandles as $ handle ) {
175+ foreach ($ this ->fileHandles as $ type => $ handle ) {
176+ ftruncate ($ handle , 0 );
171177 fclose ($ handle );
178+ flock ($ this ->lockHandles [$ type ], LOCK_UN );
179+ fclose ($ this ->lockHandles [$ type ]);
172180 }
173- $ this ->fileHandles = array ();
181+ $ this ->fileHandles = $ this -> lockHandles = array ();
174182 }
175183
176184 /**
@@ -185,17 +193,4 @@ public static function create(Process $process, $input)
185193 {
186194 return new static ($ process ->isOutputDisabled (), $ input );
187195 }
188-
189- /**
190- * Removes temporary files.
191- */
192- private function removeFiles ()
193- {
194- foreach ($ this ->files as $ filename ) {
195- if (file_exists ($ filename )) {
196- @unlink ($ filename );
197- }
198- }
199- $ this ->files = array ();
200- }
201196}
0 commit comments