11#include "mcrl2/smt/child_process.h"
12#include "mcrl2/utilities/exception.h"
13#include "mcrl2/utilities/platform.h"
15#ifdef MCRL2_PLATFORM_WINDOWS
22 #include <sys/select.h>
36#ifdef MCRL2_PLATFORM_WINDOWS
101 throw mcrl2::
runtime_error(
"Could not connect to SMT solver: failed to create pipe Stdout");
106 throw mcrl2::
runtime_error(
"Could not modify SMT solver handle: SetHandleInformation Stdout");
111 throw mcrl2::
runtime_error(
"Could not connect to SMT solver: failed to create pipe Stdin");
116 throw mcrl2::
runtime_error(
"Could not modify SMT solver handle: SetHandleInformation Stdin");
183 if(::write(m_pimpl->pipe_stdin[1], command.c_str(), command.size()) < 0)
193 int count = ::read(m_pimpl->pipe_stdout[0], output, 512);
196 return std::string(output, count);
202 while(
int i = ::read(m_pimpl->pipe_stderr[0], output, 512))
204 message.append(output, 0, i);
207 throw mcrl2::
runtime_error(
"Reading from child process " +
m_name +
" failed: " + message);
215 tv.tv_usec = timeout.count();
219 FD_SET(m_pimpl->pipe_stdout[0], &readfds);
221 int result = ::select(m_pimpl->pipe_stdout[0] + 1, &readfds, NULL, NULL, &tv);
225 throw mcrl2::runtime_error(
"Error while waiting for input from " +
m_name);
236 ::kill(m_pimpl->child_pid, SIGINT);
241 signal(SIGPIPE, SIG_IGN);
242 m_pimpl = std::make_shared<child_process::platform_impl>();
244 if (::pipe(&m_pimpl->pipe_stdin[0]) < 0)
246 throw mcrl2::runtime_error(
"failed to create pipe");
249 if (::pipe(&m_pimpl->pipe_stdout[0]) < 0)
251 throw mcrl2::runtime_error(
"failed to create pipe");
254 if (::pipe(&m_pimpl->pipe_stderr[0]) < 0)
256 throw mcrl2::runtime_error(
"failed to create pipe");
260 pid_t pid = ::fork();
264 ::dup2(m_pimpl->pipe_stdin[0], STDIN_FILENO);
265 ::dup2(m_pimpl->pipe_stdout[1], STDOUT_FILENO);
266 ::dup2(m_pimpl->pipe_stderr[1], STDERR_FILENO);
268 ::close(m_pimpl->pipe_stdin[1]);
269 ::close(m_pimpl->pipe_stdout[0]);
270 ::close(m_pimpl->pipe_stderr[0]);
272 ::execlp(
"z3",
"z3",
"-smt2",
"-in", (
char*)
nullptr);
278 ::close(m_pimpl->pipe_stdin[0]);
279 ::close(m_pimpl->pipe_stdin[1]);
280 ::close(m_pimpl->pipe_stdout[0]);
281 ::close(m_pimpl->pipe_stdout[1]);
282 ::close(m_pimpl->pipe_stderr[0]);
283 ::close(m_pimpl->pipe_stderr[1]);
285 throw mcrl2::
runtime_error(
"Problem occurred while forking SMT solver process: " + std::string(strerror(errno)) +
".\nIs " +
m_name +
" in your path?");
289 m_pimpl->child_pid = pid;
290 ::close(m_pimpl->pipe_stdin[0]);
291 ::close(m_pimpl->pipe_stdout[1]);
292 ::close(m_pimpl->pipe_stderr[1]);
300 ::close(m_pimpl->pipe_stdin[1]);
301 ::close(m_pimpl->pipe_stdout[0]);
302 ::close(m_pimpl->pipe_stderr[0]);
305 ::wait(&return_status);
Standard exception class for reporting runtime errors.
std::string read() const
Read output from the child process. This is a blocking call.
void send_sigint() const
Send the SIGINT signal to the child.
std::string read(const std::chrono::microseconds &timeout) const
Read output from the child process. If no output is available before the timeout happens,...
void write(const std::string &s) const
std::size_t operator()(const atermpp::detail::reference_aterm< T > &t) const