From d5541e44feaa2be10c6a4ffb2746d59bb01a2b26 Mon Sep 17 00:00:00 2001 From: xiphon Date: Mon, 1 Oct 2018 06:39:37 +0000 Subject: common: Windows 'spawn' support for tx and block notifications --- src/common/CMakeLists.txt | 4 +- src/common/exec.cpp | 88 ----------------------------- src/common/exec.h | 36 ------------ src/common/notify.cpp | 13 +++-- src/common/spawn.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++++++ src/common/spawn.h | 36 ++++++++++++ 6 files changed, 186 insertions(+), 132 deletions(-) delete mode 100644 src/common/exec.cpp delete mode 100644 src/common/exec.h create mode 100644 src/common/spawn.cpp create mode 100644 src/common/spawn.h (limited to 'src/common') diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 9b83f149f..aed9bfee7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -34,13 +34,13 @@ set(common_sources dns_utils.cpp download.cpp error.cpp - exec.cpp expect.cpp util.cpp i18n.cpp notify.cpp password.cpp perf_timer.cpp + spawn.cpp threadpool.cpp updates.cpp aligned.c) @@ -60,7 +60,6 @@ set(common_private_headers dns_utils.h download.h error.h - exec.h expect.h http_connection.h int-util.h @@ -74,6 +73,7 @@ set(common_private_headers i18n.h password.h perf_timer.h + spawn.h stack_trace.h threadpool.h updates.h diff --git a/src/common/exec.cpp b/src/common/exec.cpp deleted file mode 100644 index 41b8f1378..000000000 --- a/src/common/exec.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include - -#include "misc_log_ex.h" -#include "exec.h" - -namespace tools -{ - -int exec(const char *filename, char * const argv[], bool wait) -{ - pid_t pid = fork(); - if (pid < 0) - { - MERROR("Error forking: " << strerror(errno)); - return -1; - } - - // child - if (pid == 0) - { - char *envp[] = {NULL}; - execve(filename, argv, envp); - MERROR("Failed to execve: " << strerror(errno)); - return -1; - } - - // parent - if (pid > 0) - { - if (!wait) - return 0; - - while (1) - { - int wstatus = 0; - pid_t w = waitpid(pid, &wstatus, WUNTRACED | WCONTINUED); - if (w < 0) { - MERROR("Error waiting for child: " << strerror(errno)); - return -1; - } - if (WIFEXITED(wstatus)) - { - MINFO("Child exited with " << WEXITSTATUS(wstatus)); - return WEXITSTATUS(wstatus); - } - if (WIFSIGNALED(wstatus)) - { - MINFO("Child killed by " << WEXITSTATUS(wstatus)); - return WEXITSTATUS(wstatus); - } - } - } - MERROR("Secret passage found"); - return -1; -} - -} diff --git a/src/common/exec.h b/src/common/exec.h deleted file mode 100644 index 4d2037798..000000000 --- a/src/common/exec.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2018, The Monero Project -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without modification, are -// permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of -// conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list -// of conditions and the following disclaimer in the documentation and/or other -// materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be -// used to endorse or promote products derived from this software without specific -// prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -namespace tools -{ - -int exec(const char *filename, char * const argv[], bool wait); - -} diff --git a/src/common/notify.cpp b/src/common/notify.cpp index b7869ad84..cadc68ea7 100644 --- a/src/common/notify.cpp +++ b/src/common/notify.cpp @@ -29,12 +29,17 @@ #include #include "misc_log_ex.h" #include "file_io_utils.h" -#include "exec.h" +#include "spawn.h" #include "notify.h" namespace tools { +/* + TODO: + - Improve tokenization to handle paths containing whitespaces, quotes, etc. + - Windows unicode support (implies implementing unicode command line parsing code) +*/ Notify::Notify(const char *spec) { CHECK_AND_ASSERT_THROW_MES(spec, "Null spec"); @@ -51,11 +56,7 @@ int Notify::notify(const char *parameter) for (std::string &s: margs) boost::replace_all(s, "%s", parameter); - char **cargs = (char**)alloca(sizeof(char*) * (margs.size() + 1)); - for (size_t n = 0; n < margs.size(); ++n) - cargs[n] = (char*)margs[n].c_str(); - cargs[margs.size()] = NULL; - return tools::exec(filename.c_str(), cargs, false); + return tools::spawn(filename.c_str(), margs, false); } } diff --git a/src/common/spawn.cpp b/src/common/spawn.cpp new file mode 100644 index 000000000..59f11675c --- /dev/null +++ b/src/common/spawn.cpp @@ -0,0 +1,141 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#ifdef _WIN32 +#include +#include +#include +#else +#include +#endif + +#include "misc_log_ex.h" +#include "spawn.h" + +namespace tools +{ + +int spawn(const char *filename, const std::vector& args, bool wait) +{ +#ifdef _WIN32 + std::string joined = boost::algorithm::join(args, " "); + char *commandLine = !joined.empty() ? &joined[0] : nullptr; + STARTUPINFOA si = {}; + si.cb = sizeof(si); + PROCESS_INFORMATION pi; + if (!CreateProcessA(filename, commandLine, nullptr, nullptr, false, 0, nullptr, nullptr, &si, &pi)) + { + MERROR("CreateProcess failed. Error code " << GetLastError()); + return -1; + } + + BOOST_SCOPE_EXIT(&pi) + { + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + } + BOOST_SCOPE_EXIT_END + + if (!wait) + { + return 0; + } + + DWORD result = WaitForSingleObject(pi.hProcess, INFINITE); + if (result != WAIT_OBJECT_0) + { + MERROR("WaitForSingleObject failed. Result " << result << ", error code " << GetLastError()); + return -1; + } + + DWORD exitCode; + if (!GetExitCodeProcess(pi.hProcess, &exitCode)) + { + MERROR("GetExitCodeProcess failed. Error code " << GetLastError()); + return -1; + } + + MINFO("Child exited with " << exitCode); + return static_cast(exitCode); +#else + char **argv = (char**)alloca(sizeof(char*) * (args.size() + 1)); + for (size_t n = 0; n < args.size(); ++n) + argv[n] = (char*)args[n].c_str(); + argv[args.size()] = NULL; + + pid_t pid = fork(); + if (pid < 0) + { + MERROR("Error forking: " << strerror(errno)); + return -1; + } + + // child + if (pid == 0) + { + char *envp[] = {NULL}; + execve(filename, argv, envp); + MERROR("Failed to execve: " << strerror(errno)); + return -1; + } + + // parent + if (pid > 0) + { + if (!wait) + return 0; + + while (1) + { + int wstatus = 0; + pid_t w = waitpid(pid, &wstatus, WUNTRACED | WCONTINUED); + if (w < 0) { + MERROR("Error waiting for child: " << strerror(errno)); + return -1; + } + if (WIFEXITED(wstatus)) + { + MINFO("Child exited with " << WEXITSTATUS(wstatus)); + return WEXITSTATUS(wstatus); + } + if (WIFSIGNALED(wstatus)) + { + MINFO("Child killed by " << WEXITSTATUS(wstatus)); + return WEXITSTATUS(wstatus); + } + } + } + MERROR("Secret passage found"); + return -1; +#endif +} + +} diff --git a/src/common/spawn.h b/src/common/spawn.h new file mode 100644 index 000000000..c90a0f790 --- /dev/null +++ b/src/common/spawn.h @@ -0,0 +1,36 @@ +// Copyright (c) 2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +namespace tools +{ + +int spawn(const char *filename, const std::vector& args, bool wait); + +} -- cgit v1.2.3