Skip to content

Commit 5917ab4

Browse files
Merge pull request #6602 from thomasspriggs/tas/piped_process_windows_fix
Bug fix piped process on Windows
2 parents a0fe71a + 7eb82ea commit 5917ab4

File tree

9 files changed

+53
-27
lines changed

9 files changed

+53
-27
lines changed

.github/workflows/pull-request-checks.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ jobs:
482482
- name: Run CBMC and JBMC unit tests
483483
run: |
484484
make CXX=clcache BUILD_ENV=MSVC -C unit test
485+
make CXX=clcache BUILD_ENV=MSVC -C unit test TAGS="[z3]"
485486
make CXX=clcache BUILD_ENV=MSVC -C jbmc/unit test
486487
- name: Run CBMC regression tests
487488
run: make CXX=clcache BUILD_ENV=MSVC -C regression test

regression/cbmc-incr-smt2/nondeterministic-int-assert/control_flow.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
CORE winbug
1+
CORE
22
control_flow.c
3-
--incremental-smt2-solver "z3 --smt2 -in" --verbosity 10
3+
--incremental-smt2-solver 'z3 --smt2 -in' --verbosity 10
44
Passing problem to incremental SMT2 solving via "z3 --smt2 -in"
55
Sending command to SMT2 solver - \(set-option :produce-models true\)
66
Sending command to SMT2 solver - \(set-logic QF_UFBV\)

regression/cbmc-incr-smt2/nondeterministic-int-assert/incremental_solver_called.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
CORE winbug
1+
CORE
22
test.c
3-
--incremental-smt2-solver "z3 --smt2 -in" --verbosity 10
3+
--incremental-smt2-solver 'z3 --smt2 -in' --verbosity 10
44
Passing problem to incremental SMT2 solving via "z3 --smt2 -in"
55
Sending command to SMT2 solver - \(set-option :produce-models true\)
66
Sending command to SMT2 solver - \(set-logic QF_UFBV\)

regression/cbmc-incr-smt2/nondeterministic-int-assert/trace.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
CORE winbug
1+
CORE
22
trace.c
3-
--incremental-smt2-solver "z3 --smt2 -in" --trace
3+
--incremental-smt2-solver 'z3 --smt2 -in' --trace
44
Passing problem to incremental SMT2 solving via "z3 --smt2 -in"
55
Assert of inequality to 4\.: FAILURE
66
Assert of inequality to 2\.: FAILURE

regression/cbmc-incr-smt2/nondeterministic-int-assert/valid_unsat.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
CORE winbug
1+
CORE
22
valid_unsat.c
3-
--incremental-smt2-solver "z3 --smt2 -in" --verbosity 10
3+
--incremental-smt2-solver 'z3 --smt2 -in' --verbosity 10
44
Passing problem to incremental SMT2 solving via "z3 --smt2 -in"
55
Sending command to SMT2 solver - \(check-sat\)
66
Solver response - unsat

src/solvers/smt2_incremental/smt_solver_process.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,17 @@ void smt_piped_solver_processt::send(const smt_commandt &smt_command)
2828
const std::string command_string = smt_to_smt2_string(smt_command);
2929
log.debug() << "Sending command to SMT2 solver - " << command_string
3030
<< messaget::eom;
31-
process.send(command_string + "\n");
31+
const auto response = process.send(command_string + "\n");
32+
switch(response)
33+
{
34+
case piped_processt::send_responset::SUCCEEDED:
35+
return;
36+
case piped_processt::send_responset::FAILED:
37+
throw analysis_exceptiont{"Sending to SMT solver sub process failed."};
38+
case piped_processt::send_responset::ERRORED:
39+
throw analysis_exceptiont{"SMT solver sub process is in error state."};
40+
}
41+
UNREACHABLE;
3242
}
3343

3444
/// Log messages and throw exception.

src/util/piped_process.cpp

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ piped_processt::piped_processt(const std::vector<std::string> &commandvec)
138138
// Use process ID as a unique ID for this process at this time.
139139
base_name.append(std::to_string(GetCurrentProcessId()));
140140
const std::string in_name = base_name + "\\IN";
141-
child_std_IN_Rd = CreateNamedPipe(
141+
child_std_IN_Wr = CreateNamedPipe(
142142
in_name.c_str(),
143-
PIPE_ACCESS_INBOUND, // Reading for us
143+
PIPE_ACCESS_OUTBOUND, // Writing for us
144144
PIPE_TYPE_BYTE | PIPE_NOWAIT, // Bytes and non-blocking
145145
PIPE_UNLIMITED_INSTANCES, // Probably doesn't matter
146146
BUFSIZE,
@@ -156,9 +156,9 @@ piped_processt::piped_processt(const std::vector<std::string> &commandvec)
156156
throw system_exceptiont("Input pipe creation failed for child_std_IN_Rd");
157157
}
158158
// Connect to the other side of the pipe
159-
child_std_IN_Wr = CreateFileA(
159+
child_std_IN_Rd = CreateFile(
160160
in_name.c_str(),
161-
GENERIC_WRITE, // Write side
161+
GENERIC_READ, // Read side
162162
FILE_SHARE_READ | FILE_SHARE_WRITE, // Shared read/write
163163
&sec_attr, // Need this for inherit
164164
OPEN_EXISTING, // Opening other end
@@ -168,7 +168,8 @@ piped_processt::piped_processt(const std::vector<std::string> &commandvec)
168168
{
169169
throw system_exceptiont("Input pipe creation failed for child_std_IN_Wr");
170170
}
171-
if(!SetHandleInformation(child_std_IN_Rd, HANDLE_FLAG_INHERIT, 0))
171+
if(!SetHandleInformation(
172+
child_std_IN_Rd, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
172173
{
173174
throw system_exceptiont(
174175
"Input pipe creation failed on SetHandleInformation");
@@ -187,7 +188,7 @@ piped_processt::piped_processt(const std::vector<std::string> &commandvec)
187188
{
188189
throw system_exceptiont("Output pipe creation failed for child_std_OUT_Rd");
189190
}
190-
child_std_OUT_Wr = CreateFileA(
191+
child_std_OUT_Wr = CreateFile(
191192
out_name.c_str(),
192193
GENERIC_WRITE, // Write side
193194
FILE_SHARE_READ | FILE_SHARE_WRITE, // Shared read/write
@@ -233,6 +234,8 @@ piped_processt::piped_processt(const std::vector<std::string> &commandvec)
233234
// recognize that the child process has ended (but maybe we don't care).
234235
CloseHandle(child_std_OUT_Wr);
235236
CloseHandle(child_std_IN_Rd);
237+
if(!success)
238+
throw system_exceptiont("Process creation failed.");
236239
# else
237240

238241
if(pipe(pipe_input) == -1)
@@ -335,18 +338,25 @@ piped_processt::~piped_processt()
335338
# endif
336339
}
337340

341+
NODISCARD
338342
piped_processt::send_responset piped_processt::send(const std::string &message)
339343
{
340344
if(process_state != statet::RUNNING)
341345
{
342346
return send_responset::ERRORED;
343347
}
344348
#ifdef _WIN32
345-
if(!WriteFile(child_std_IN_Wr, message.c_str(), message.size(), NULL, NULL))
349+
const auto message_size = narrow<DWORD>(message.size());
350+
DWORD bytes_written = 0;
351+
if(!WriteFile(
352+
child_std_IN_Wr, message.c_str(), message_size, &bytes_written, NULL))
346353
{
347354
// Error handling with GetLastError ?
348355
return send_responset::FAILED;
349356
}
357+
INVARIANT(
358+
message_size == bytes_written,
359+
"Number of bytes written to sub process must match message size.");
350360
#else
351361
// send message to solver process
352362
int send_status = fputs(message.c_str(), command_stream);
@@ -415,15 +425,22 @@ bool piped_processt::can_receive(optionalt<std::size_t> wait_time)
415425
const int timeout = wait_time ? narrow<int>(*wait_time) : -1;
416426
#ifdef _WIN32
417427
int waited_time = 0;
418-
// The next four need to be initialised for compiler warnings
419-
DWORD buffer = 0;
420-
LPDWORD nbytes = 0;
421-
LPDWORD rbytes = 0;
422-
LPDWORD rmbytes = 0;
428+
DWORD total_bytes_available = 0;
423429
while(timeout < 0 || waited_time >= timeout)
424430
{
425-
PeekNamedPipe(child_std_OUT_Rd, &buffer, 1, nbytes, rbytes, rmbytes);
426-
if(buffer != 0)
431+
const LPVOID lpBuffer = nullptr;
432+
const DWORD nBufferSize = 0;
433+
const LPDWORD lpBytesRead = nullptr;
434+
const LPDWORD lpTotalBytesAvail = &total_bytes_available;
435+
const LPDWORD lpBytesLeftThisMessage = nullptr;
436+
PeekNamedPipe(
437+
child_std_OUT_Rd,
438+
lpBuffer,
439+
nBufferSize,
440+
lpBytesRead,
441+
lpTotalBytesAvail,
442+
lpBytesLeftThisMessage);
443+
if(total_bytes_available > 0)
427444
{
428445
return true;
429446
}

src/util/piped_process.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ typedef struct _PROCESS_INFORMATION PROCESS_INFORMATION; // NOLINT
1313
typedef void *HANDLE; // NOLINT
1414
#endif
1515

16+
#include "nodiscard.h"
1617
#include "optional.h"
1718
#include <vector>
1819

@@ -42,7 +43,7 @@ class piped_processt
4243
/// Send a string message (command) to the child process.
4344
/// \param message The string message to be sent.
4445
/// \return
45-
send_responset send(const std::string &message);
46+
NODISCARD send_responset send(const std::string &message);
4647
/// Read a string from the child process' output.
4748
/// \return a string containing data from the process, empty string if no data
4849
std::string receive();

unit/util/piped_process.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,6 @@ TEST_CASE(
107107
REQUIRE(calc < 2);
108108
}
109109

110-
#ifndef _WIN32
111-
// No Windows tests for z3 due to path and dependency issues.
112110
TEST_CASE(
113111
"Creating a sub process of z3 and read a response from an echo command.",
114112
"[core][util][piped_process][.z3]")
@@ -314,4 +312,3 @@ TEST_CASE(
314312
REQUIRE(
315313
process.send("(exit)\n") == piped_processt::send_responset::SUCCEEDED);
316314
}
317-
#endif

0 commit comments

Comments
 (0)