@@ -140,40 +140,60 @@ const char* ffProcessReadOutput(FFProcessHandle* handle, FFstrbuf* buffer)
140140 int32_t timeout = instance .config .general .processingTimeout ;
141141 FF_AUTO_CLOSE_FD HANDLE hProcess = handle -> pid ;
142142 FF_AUTO_CLOSE_FD HANDLE hChildPipeRead = handle -> pipeRead ;
143+ FF_AUTO_CLOSE_FD HANDLE hReadEvent = NULL ;
143144 handle -> pid = INVALID_HANDLE_VALUE ;
144145 handle -> pipeRead = INVALID_HANDLE_VALUE ;
145146
147+ if (timeout >= 0 && !NT_SUCCESS (NtCreateEvent (& hReadEvent , EVENT_ALL_ACCESS , NULL , SynchronizationEvent , FALSE)))
148+ return "NtCreateEvent() failed" ;
149+
146150 char str [FF_PIPE_BUFSIZ ];
147- DWORD nRead = 0 ;
148- OVERLAPPED overlapped = {};
149- // ReadFile always completes synchronously if the pipe is not created with FILE_FLAG_OVERLAPPED
151+ uint32_t nRead = 0 ;
152+ IO_STATUS_BLOCK iosb = {};
150153 do
151154 {
152- if (!ReadFile (hChildPipeRead , str , sizeof (str ), & nRead , & overlapped ))
155+ NTSTATUS status = NtReadFile (
156+ hChildPipeRead ,
157+ hReadEvent ,
158+ NULL ,
159+ NULL ,
160+ & iosb ,
161+ str ,
162+ (ULONG ) sizeof (str ),
163+ NULL ,
164+ NULL
165+ );
166+ if (status == STATUS_PENDING )
153167 {
154- switch (GetLastError ( ))
168+ switch (NtWaitForSingleObject ( hReadEvent , TRUE, & ( LARGE_INTEGER ) { . QuadPart = ( int64_t ) timeout * -10000 } ))
155169 {
156- case ERROR_IO_PENDING :
157- if (!GetOverlappedResultEx (hChildPipeRead , & overlapped , & nRead , timeout < 0 ? INFINITE : (DWORD ) timeout , FALSE))
158- {
159- if (GetLastError () == ERROR_BROKEN_PIPE )
160- return NULL ;
161-
162- CancelIo (hChildPipeRead );
163- TerminateProcess (hProcess , 1 );
164- return "GetOverlappedResultEx(hChildPipeRead) failed" ;
165- }
170+ case STATUS_WAIT_0 :
171+ status = iosb .Status ;
166172 break ;
167173
168- case ERROR_BROKEN_PIPE :
169- goto exit ;
174+ case STATUS_TIMEOUT :
175+ CancelIo (hChildPipeRead );
176+ TerminateProcess (hProcess , 1 );
177+ return "NtReadFile(hChildPipeRead) timed out" ;
170178
171179 default :
172180 CancelIo (hChildPipeRead );
173181 TerminateProcess (hProcess , 1 );
174- return "ReadFile(hChildPipeRead ) failed" ;
182+ return "WaitForSingleObject(hReadEvent ) failed" ;
175183 }
176184 }
185+
186+ if (status == STATUS_PIPE_BROKEN || status == STATUS_END_OF_FILE )
187+ goto exit ;
188+
189+ if (!NT_SUCCESS (status ))
190+ {
191+ CancelIo (hChildPipeRead );
192+ TerminateProcess (hProcess , 1 );
193+ return "NtReadFile(hChildPipeRead) failed" ;
194+ }
195+
196+ nRead = (uint32_t ) iosb .Information ;
177197 ffStrbufAppendNS (buffer , nRead , str );
178198 } while (nRead > 0 );
179199
0 commit comments