@@ -28,6 +28,7 @@ class WindowsPipes extends AbstractPipes
28
28
{
29
29
private $ files = array ();
30
30
private $ fileHandles = array ();
31
+ private $ lockHandles = array ();
31
32
private $ readBytes = array (
32
33
Process::STDOUT => 0 ,
33
34
Process::STDERR => 0 ,
@@ -54,24 +55,31 @@ public function __construct($disableOutput, $input)
54
55
for ($ i = 0 ;; ++$ i ) {
55
56
foreach ($ pipes as $ pipe => $ name ) {
56
57
$ 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 ) {
58
+
59
+ if (!$ h = fopen ($ file .'.lock ' , 'w ' )) {
62
60
$ error = $ lastError ;
63
61
if ($ tmpCheck || $ tmpCheck = unlink (tempnam (false , 'sf_check_ ' ))) {
64
- continue ;
62
+ continue 2 ;
65
63
}
66
64
restore_error_handler ();
67
65
throw new RuntimeException (sprintf ('A temporary file could not be opened to write the process output: %s ' , $ error ));
68
66
}
69
- if (!$ h || ! $ this -> fileHandles [ $ pipe ] = fopen ( $ file , ' rb ' )) {
67
+ if (!flock ( $ h , LOCK_EX | LOCK_NB )) {
70
68
continue 2 ;
71
69
}
72
- if (isset ($ this ->files [$ pipe ])) {
73
- unlink ($ this ->files [$ pipe ]);
70
+ if (isset ($ this ->lockHandles [$ pipe ])) {
71
+ flock ($ this ->lockHandles [$ pipe ], LOCK_UN );
72
+ fclose ($ this ->lockHandles [$ pipe ]);
74
73
}
74
+ $ this ->lockHandles [$ pipe ] = $ h ;
75
+
76
+ if (!$ h = fopen ($ file , 'w+ ' )) {
77
+ flock ($ this ->lockHandles [$ pipe ], LOCK_UN );
78
+ fclose ($ this ->lockHandles [$ pipe ]);
79
+ unset($ this ->lockHandles [$ pipe ]);
80
+ continue 2 ;
81
+ }
82
+ $ this ->fileHandles [$ pipe ] = $ h ;
75
83
$ this ->files [$ pipe ] = $ file ;
76
84
}
77
85
break ;
@@ -85,7 +93,6 @@ public function __construct($disableOutput, $input)
85
93
public function __destruct ()
86
94
{
87
95
$ this ->close ();
88
- $ this ->removeFiles ();
89
96
}
90
97
91
98
/**
@@ -145,8 +152,11 @@ public function readAndWrite($blocking, $close = false)
145
152
$ read [$ type ] = $ data ;
146
153
}
147
154
if ($ close ) {
155
+ ftruncate ($ fileHandle , 0 );
148
156
fclose ($ fileHandle );
149
- unset($ this ->fileHandles [$ type ]);
157
+ flock ($ this ->lockHandles [$ type ], LOCK_UN );
158
+ fclose ($ this ->lockHandles [$ type ]);
159
+ unset($ this ->fileHandles [$ type ], $ this ->lockHandles [$ type ]);
150
160
}
151
161
}
152
162
@@ -167,10 +177,13 @@ public function areOpen()
167
177
public function close ()
168
178
{
169
179
parent ::close ();
170
- foreach ($ this ->fileHandles as $ handle ) {
180
+ foreach ($ this ->fileHandles as $ type => $ handle ) {
181
+ ftruncate ($ handle , 0 );
171
182
fclose ($ handle );
183
+ flock ($ this ->lockHandles [$ type ], LOCK_UN );
184
+ fclose ($ this ->lockHandles [$ type ]);
172
185
}
173
- $ this ->fileHandles = array ();
186
+ $ this ->fileHandles = $ this -> lockHandles = array ();
174
187
}
175
188
176
189
/**
@@ -185,17 +198,4 @@ public static function create(Process $process, $input)
185
198
{
186
199
return new static ($ process ->isOutputDisabled (), $ input );
187
200
}
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
- }
201
201
}
0 commit comments