@@ -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 ,
@@ -47,31 +48,33 @@ public function __construct($disableOutput, $input)
47
48
Process::STDOUT => Process::OUT ,
48
49
Process::STDERR => Process::ERR ,
49
50
);
50
- $ tmpCheck = false ;
51
51
$ tmpDir = sys_get_temp_dir ();
52
52
$ lastError = 'unknown reason ' ;
53
53
set_error_handler (function ($ type , $ msg ) use (&$ lastError ) { $ lastError = $ msg ; });
54
54
for ($ i = 0 ;; ++$ i ) {
55
55
foreach ($ pipes as $ pipe => $ name ) {
56
56
$ 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 ' )) {
66
59
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 ));
68
61
}
69
- if (!$ h || ! $ this -> fileHandles [ $ pipe ] = fopen ( $ file , ' rb ' )) {
62
+ if (!flock ( $ h , LOCK_EX | LOCK_NB )) {
70
63
continue 2 ;
71
64
}
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 ]);
74
68
}
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 ;
75
78
$ this ->files [$ pipe ] = $ file ;
76
79
}
77
80
break ;
@@ -85,7 +88,6 @@ public function __construct($disableOutput, $input)
85
88
public function __destruct ()
86
89
{
87
90
$ this ->close ();
88
- $ this ->removeFiles ();
89
91
}
90
92
91
93
/**
@@ -145,8 +147,11 @@ public function readAndWrite($blocking, $close = false)
145
147
$ read [$ type ] = $ data ;
146
148
}
147
149
if ($ close ) {
150
+ ftruncate ($ fileHandle , 0 );
148
151
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 ]);
150
155
}
151
156
}
152
157
@@ -167,10 +172,13 @@ public function areOpen()
167
172
public function close ()
168
173
{
169
174
parent ::close ();
170
- foreach ($ this ->fileHandles as $ handle ) {
175
+ foreach ($ this ->fileHandles as $ type => $ handle ) {
176
+ ftruncate ($ handle , 0 );
171
177
fclose ($ handle );
178
+ flock ($ this ->lockHandles [$ type ], LOCK_UN );
179
+ fclose ($ this ->lockHandles [$ type ]);
172
180
}
173
- $ this ->fileHandles = array ();
181
+ $ this ->fileHandles = $ this -> lockHandles = array ();
174
182
}
175
183
176
184
/**
@@ -185,17 +193,4 @@ public static function create(Process $process, $input)
185
193
{
186
194
return new static ($ process ->isOutputDisabled (), $ input );
187
195
}
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
196
}
0 commit comments