127 const std::vector<std::string> &commandvec,
129 : log{message_handler}
133 SECURITY_ATTRIBUTES sec_attr;
134 sec_attr.nLength =
sizeof(SECURITY_ATTRIBUTES);
136 sec_attr.bInheritHandle =
TRUE;
140 sec_attr.lpSecurityDescriptor = NULL;
143 std::string base_name =
"\\\\.\\pipe\\cbmc\\child\\";
145 base_name.append(std::to_string(GetCurrentProcessId()));
146 const std::string in_name = base_name +
"\\IN";
147 child_std_IN_Wr = CreateNamedPipe(
149 PIPE_ACCESS_OUTBOUND,
150 PIPE_TYPE_BYTE | PIPE_NOWAIT,
151 PIPE_UNLIMITED_INSTANCES,
160 if(child_std_IN_Rd == INVALID_HANDLE_VALUE)
165 child_std_IN_Rd = CreateFile(
168 FILE_SHARE_READ | FILE_SHARE_WRITE,
171 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING,
173 if(child_std_IN_Wr == INVALID_HANDLE_VALUE)
177 if(!SetHandleInformation(
178 child_std_IN_Rd, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
181 "Input pipe creation failed on SetHandleInformation");
183 const std::string out_name = base_name +
"\\OUT";
184 child_std_OUT_Rd = CreateNamedPipe(
187 PIPE_TYPE_BYTE | PIPE_NOWAIT,
188 PIPE_UNLIMITED_INSTANCES,
193 if(child_std_OUT_Rd == INVALID_HANDLE_VALUE)
197 child_std_OUT_Wr = CreateFile(
200 FILE_SHARE_READ | FILE_SHARE_WRITE,
203 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING,
205 if(child_std_OUT_Wr == INVALID_HANDLE_VALUE)
209 if(!SetHandleInformation(child_std_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
212 "Output pipe creation failed on SetHandleInformation");
215 STARTUPINFOW start_info;
217 ZeroMemory(proc_info.get(),
sizeof(PROCESS_INFORMATION));
218 ZeroMemory(&start_info,
sizeof(STARTUPINFOW));
219 start_info.cb =
sizeof(STARTUPINFOW);
220 start_info.hStdError = child_std_OUT_Wr;
221 start_info.hStdOutput = child_std_OUT_Wr;
222 start_info.hStdInput = child_std_IN_Rd;
223 start_info.dwFlags |= STARTF_USESTDHANDLES;
224 const std::wstring cmdline = prepare_windows_command_line(commandvec);
227 const BOOL success = CreateProcessW(
229 _wcsdup(cmdline.c_str()),
241 CloseHandle(child_std_OUT_Wr);
242 CloseHandle(child_std_IN_Rd);
282 char **args =
reinterpret_cast<char **
>(
283 malloc((commandvec.size() + 1) *
sizeof(
char *)));
286 while(i < commandvec.size())
288 args[i] = strdup(commandvec[i].c_str());
292 execvp(commandvec[0].c_str(), args);
305 std::cerr <<
"Launching " << commandvec[0]
306 <<
" failed with error: " << std::strerror(errno) << std::endl;
326 TerminateProcess(proc_info->hProcess, 0);
331 DisconnectNamedPipe(child_std_OUT_Rd);
332 DisconnectNamedPipe(child_std_IN_Wr);
333 CloseHandle(child_std_OUT_Rd);
334 CloseHandle(child_std_IN_Wr);
335 CloseHandle(proc_info->hProcess);
336 CloseHandle(proc_info->hThread);
357 DWORD bytes_written = 0;
358 const int retry_limit = 10;
359 for(
int send_attempts = 0; send_attempts < retry_limit; ++send_attempts)
368 child_std_IN_Wr, message.c_str(), message_size, &bytes_written, NULL))
370 const DWORD error_code = GetLastError();
371 log.
debug() <<
"Last error code is " + std::to_string(error_code)
375 if(bytes_written != 0)
378 const auto wait_milliseconds =
narrow<DWORD>(1 << send_attempts);
379 log.
debug() <<
"Zero bytes send to sub process. Retrying in "
381 FlushFileBuffers(child_std_IN_Wr);
382 Sleep(wait_milliseconds);
385 message_size == bytes_written,
386 "Number of bytes written to sub process must match message size."
388 std::to_string(message_size) +
" but " + std::to_string(bytes_written) +
389 " bytes were written.");
395 if(send_status == EOF)
455 const int timeout = wait_time ?
narrow<int>(*wait_time) : -1;
458 DWORD total_bytes_available = 0;
459 while(timeout < 0 || waited_time >= timeout)
461 const LPVOID lpBuffer =
nullptr;
462 const DWORD nBufferSize = 0;
463 const LPDWORD lpBytesRead =
nullptr;
464 const LPDWORD lpTotalBytesAvail = &total_bytes_available;
465 const LPDWORD lpBytesLeftThisMessage =
nullptr;
472 lpBytesLeftThisMessage);
473 if(total_bytes_available > 0)
478# define WIN_POLL_WAIT 10
479 Sleep(WIN_POLL_WAIT);
480 waited_time += WIN_POLL_WAIT;
485 pipe_output[0], POLLIN, 0
487 nfds_t nfds = POLLIN;
488 const int ready = poll(&fds, nfds, timeout);
504 if(fds.revents & POLLIN)