2
0
mirror of https://github.com/boostorg/process.git synced 2026-01-20 16:52:14 +00:00

Compare commits

...

32 Commits

Author SHA1 Message Date
Klemens Morgenstern
0341e08297 Merge pull request #212 from klemens-morgenstern/develop
Master update
2019-12-29 04:37:11 +08:00
Klemens David Morgenstern
5853345715 trying to fix appveyor to upload to report.ci 2019-12-29 04:16:44 +08:00
Klemens David Morgenstern
41f8b1cf00 removed sigtimedwait for group_wait 2019-12-29 03:39:32 +08:00
Klemens David Morgenstern
56ae00c7a4 typo fix 2019-12-29 00:48:51 +08:00
Klemens David Morgenstern
f58882c956 small travis fixes, hopefully fixing the build 2019-12-29 00:42:21 +08:00
Klemens David Morgenstern
3f14ebc755 changed report script 2019-12-29 00:04:26 +08:00
Klemens David Morgenstern
6a4d2ff721 added typedef executor_type; 2019-11-22 14:03:22 +08:00
Klemens David Morgenstern
6bf37ea8e8 Merge branch 'develop' of github.com:boostorg/process into develop
# Conflicts:
#	test/async_pipe.cpp
2019-11-22 13:11:17 +08:00
Klemens Morgenstern
ad38cdfada Merge pull request #106 from treesoft-de/bugfix
fix double CloseHandle after move of file_descriptor on windows
2019-11-22 13:08:17 +08:00
Klemens Morgenstern
167ee79fa9 Merge pull request #102 from res2k/develop
Miscellaneous fixes related to POSIX environments
2019-11-22 13:07:52 +08:00
Klemens David Morgenstern
6b83d0b9dd closes boostorg/process#97 2019-11-22 13:07:08 +08:00
Klemens Morgenstern
16d16d40be Merge pull request #90 from BikingGlobetrotter/develop
fixed hidden local variable
2019-11-22 13:06:12 +08:00
Klemens David Morgenstern
f5f0866745 closes boostorg/process#103 2019-11-22 13:04:59 +08:00
Klemens Morgenstern
408cff1997 Merge pull request #70 from thomassuckow/patch-1
Guard against EINTR in basic_pipe
2019-11-22 13:01:52 +08:00
Klemens David Morgenstern
09faec4732 closes boostorg/process#104 2019-11-22 12:59:05 +08:00
Klemens Morgenstern
5ab43529b7 Merge pull request #209 from killerbot242/changes3
only carry out when buffer size is > 0
2019-11-22 12:52:41 +08:00
Klemens Morgenstern
97f5b3c049 Merge pull request #211 from Instand/patch
Fix basic_ipstream is_open compile error.
2019-11-22 12:51:58 +08:00
Klemens David Morgenstern
6dd3e0bdb4 typo fix, closes klemens-morgenstern/boost-process#210 2019-11-22 12:50:40 +08:00
Arew
eba5cb7be2 Fix basic_ipstream is_open compile error. 2019-11-21 17:57:24 +03:00
Klemens David Morgenstern
f4c51bcd5a closes klemens-morgenstern/boost-process#107 2019-10-26 11:04:42 +07:00
Raymond Häb
410c0d592e fix double CloseHandle after move of file_descriptor on windows 2019-10-18 10:08:21 +02:00
Frank Richter
40df7899b2 test: Add test for direct conversion of wnative_environment to native_environment 2019-09-11 11:31:19 +02:00
Frank Richter
51083a8fa8 posix environment: Fix assignment of wnative_environment to wenvironment
Using 'environ' as the native_handle for a wide environment doesn't work,
as environ returns char**. Instead, use data we already converted.
2019-09-11 11:23:36 +02:00
Frank Richter
fe3cb0efc7 posix environment: Avoid using front() on empty string
That is undefined behaviour. Pushing a single NUL makes the string
non-empty but still gives us "".
2019-09-11 11:20:24 +02:00
Frank Richter
e0dd3b9658 test: Build fix for async_pipe 2019-09-11 11:01:45 +02:00
Lieven de Cock
d7d84f3952 only carry out when buffer size is > 0 2019-08-19 12:11:34 +02:00
Klemens Morgenstern
6ccce9104a Merge pull request #91 from orgads/patch-1
Fix GCC9 warning
2019-06-26 20:30:18 +10:00
Orgad Shaneh
984c0c5b71 Fix GCC9 warning
warning: moving a local object in a return statement prevents copy elision
2019-06-26 13:11:49 +03:00
michael
43523fcf8b fixed hidden local variable 2019-06-21 13:39:54 +02:00
Klemens Morgenstern
cf7ad36438 Merge pull request #87 from OBorce/feature/fix-stream-move-assignments
fix move assignment operators for basic_[io]pstream
2019-06-06 11:30:33 +07:00
boris
ca994c1972 fix move assignment operators for basic_[io]pstream 2019-06-05 00:19:53 +02:00
Thomas Suckow
1b6ccb6d39 Guard against EINTR in basic_pipe
Based on the code from executor.hpp, a signal can cause invoking a child process to fail because reading/writing the pipe was interrupted.
2019-01-22 09:22:52 -08:00
18 changed files with 196 additions and 103 deletions

View File

@@ -85,7 +85,7 @@ before_install:
- git checkout $BOOST_BRANCH
- git submodule update --init --merge
- git remote set-branches --add origin $BOOST_BRANCH
- git pull --recurse-submodules
- git pull --recurse-submodules || true
- git submodule update --init
- git checkout $BOOST_BRANCH
- git submodule foreach "git reset --quiet --hard; git clean -fxd"
@@ -131,6 +131,7 @@ after_success:
- coveralls-lcov coverals/coverage.info
after_script:
- curl -s https://report.ci/upload.py | python - --name="$BADGE test run"
- bash <(curl -s https://codecov.io/bash)
- cd $BOOST/libs/$PROJECT_TO_TEST/test
- curl -s https://report.ci/upload.py | python - --name="$BADGE test run" --root_dir $BOOST

View File

@@ -20,7 +20,7 @@ Though please note, that if the the same thread reads and write to a pipe, it wi
[section:anonymous Anonymous Pipes]
The usual type of pipes, are the anonymous ones. Since the have no name,
The most common pipes are anonymous. Since the have no name,
a handle to them can only be obtained from duplicating either handle.
In this library the following functions are used for the creation of unnamed pipes:

View File

@@ -47,6 +47,8 @@ public:
*/
typedef platform_specific handle_type;
typedef typename handle_type::executor_type executor_type;
/** Construct a new async_pipe, does automatically open the pipe.
* Initializes source and sink with the same io_context.
* @note Windows creates a named pipe here, where the name is automatically generated.

View File

@@ -145,8 +145,11 @@ struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
{
std::istream is (buffer_.get());
Type arg;
arg.resize(buffer_->size());
is.read(&*arg.begin(), buffer_->size());
if (buffer_->size() > 0)
{
arg.resize(buffer_->size());
is.read(&*arg.begin(), buffer_->size());
}
promise_->set_value(std::move(arg));
}
});

View File

@@ -23,6 +23,7 @@ class async_pipe
public:
typedef int native_handle_type;
typedef ::boost::asio::posix::stream_descriptor handle_type;
typedef typename handle_type::executor_type executor_type;
inline async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios) {}

View File

@@ -82,18 +82,26 @@ public:
int_type write(const char_type * data, int_type count)
{
auto write_len = ::write(_sink, data, count * sizeof(char_type));
if (write_len == -1)
::boost::process::detail::throw_last_error();
int_type write_len;
while ((write_len = ::write(_sink, data, count * sizeof(char_type))) == -1)
{
//Try again if interrupted
auto err = errno;
if (err != EINTR)
::boost::process::detail::throw_last_error();
}
return write_len;
}
int_type read(char_type * data, int_type count)
{
auto read_len = ::read(_source, data, count * sizeof(char_type));
if (read_len == -1)
::boost::process::detail::throw_last_error();
int_type read_len;
while ((read_len = ::read(_source, data, count * sizeof(char_type))) == -1)
{
//Try again if interrupted
auto err = errno;
if (err != EINTR)
::boost::process::detail::throw_last_error();
}
return read_len;
}

View File

@@ -94,7 +94,7 @@ public:
native_environment_impl & operator=(native_environment_impl && ) = default;
native_handle_type _env_impl = _impl.data();
native_handle_type native_handle() const {return environ;}
native_handle_type native_handle() const {return _env_impl;}
};
template<>
@@ -294,7 +294,11 @@ std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basi
ret.reserve(data.size() +1);
for (auto & val : data)
{
if (val.empty())
val.push_back(0);
ret.push_back(&val.front());
}
ret.push_back(nullptr);
return ret;

View File

@@ -64,79 +64,9 @@ inline bool wait_until(
bool timed_out = false;
int ret;
#if defined(BOOST_POSIX_HAS_SIGTIMEDWAIT)
auto get_timespec =
+[](const Duration & dur)
{
::timespec ts;
ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(dur).count();
ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(dur).count() % 1000000000;
return ts;
};
::sigset_t sigset;
if (sigemptyset(&sigset) != 0)
{
ec = get_last_error();
return false;
}
if (sigaddset(&sigset, SIGCHLD) != 0)
{
ec = get_last_error();
return false;
}
struct ::sigaction old_sig;
if (-1 == ::sigaction(SIGCHLD, nullptr, &old_sig))
{
ec = get_last_error();
return false;
}
do
{
auto ts = get_timespec(time_out - Clock::now());
ret = ::sigtimedwait(&sigset, nullptr, &ts);
errno = 0;
if ((ret == SIGCHLD) && (old_sig.sa_handler != SIG_DFL) && (old_sig.sa_handler != SIG_IGN))
old_sig.sa_handler(ret);
ret = ::waitpid(-p.grp, &siginfo.si_status, 0); //so in case it exited, we wanna reap it first
if (ret == -1)
{
if ((errno == ECHILD) || (errno == ESRCH))
{
ec.clear();
return true;
}
else
{
ec = get_last_error();
return false;
}
}
//check if we're done ->
ret = ::waitid(P_PGID, p.grp, &siginfo, WEXITED | WNOHANG);
}
while (((ret != -1) || ((errno != ECHILD) && (errno != ESRCH))) && !(timed_out = (Clock::now() > time_out)));
if (errno != ECHILD)
{
ec = boost::process::detail::get_last_error();
return !timed_out;
}
else
{
ec.clear();
return true; //even if timed out, there are no child proccessess left
}
#else
::timespec sleep_interval;
sleep_interval.tv_sec = 0;
sleep_interval.tv_nsec = 1000000;
sleep_interval.tv_nsec = 100000000;
while (!(timed_out = (Clock::now() > time_out)))
@@ -156,7 +86,6 @@ inline bool wait_until(
::nanosleep(&sleep_interval, nullptr);
}
return !timed_out;
#endif
}
template< class Clock, class Duration >

View File

@@ -48,6 +48,7 @@ class async_pipe
public:
typedef ::boost::winapi::HANDLE_ native_handle_type;
typedef ::boost::asio::windows::stream_handle handle_type;
typedef typename handle_type::executor_type executor_type;
async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios, make_pipe_name(), true) {}
async_pipe(boost::asio::io_context & ios_source, boost::asio::io_context & ios_sink)

View File

@@ -11,6 +11,7 @@
#include <boost/winapi/file_management.hpp>
#include <string>
#include <boost/filesystem/path.hpp>
#include <boost/core/exchange.hpp>
namespace boost { namespace process { namespace detail { namespace windows {
@@ -90,10 +91,18 @@ struct file_descriptor
}
file_descriptor(const file_descriptor & ) = delete;
file_descriptor(file_descriptor && ) = default;
file_descriptor(file_descriptor &&other)
: _handle( boost::exchange(other._handle, ::boost::winapi::INVALID_HANDLE_VALUE_) )
{
}
file_descriptor& operator=(const file_descriptor & ) = delete;
file_descriptor& operator=(file_descriptor && ) = default;
file_descriptor& operator=(file_descriptor &&other)
{
if (_handle != ::boost::winapi::INVALID_HANDLE_VALUE_)
::boost::winapi::CloseHandle(_handle);
_handle = boost::exchange(other._handle, ::boost::winapi::INVALID_HANDLE_VALUE_);
}
~file_descriptor()
{

View File

@@ -34,12 +34,12 @@ inline std::vector<native_handle_type> get_handles(std::error_code & ec)
::boost::winapi::NTSTATUS_ nt_status = STATUS_INFO_LENGTH_MISMATCH_;
for (int cnt = 0;
for (;
nt_status == STATUS_INFO_LENGTH_MISMATCH_;
nt_status = workaround::nt_system_query_information(
workaround::SystemHandleInformation_,
info_pointer, buffer.size(),
NULL))
info_pointer, static_cast<::boost::winapi::ULONG_>(buffer.size()),
nullptr))
{
buffer.resize(buffer.size() * 2);
info_pointer = reinterpret_cast<workaround::SYSTEM_HANDLE_INFORMATION_*>(buffer.data());

View File

@@ -60,14 +60,14 @@ inline boost::filesystem::path search_path(
auto p = pp_ / filename;
for (boost::filesystem::path ext : extensions)
{
boost::filesystem::path pp = p;
pp += ext;
boost::filesystem::path pp_ext = p;
pp_ext += ext;
boost::system::error_code ec;
bool file = boost::filesystem::is_regular_file(pp, ec);
bool file = boost::filesystem::is_regular_file(pp_ext, ec);
if (!ec && file &&
::boost::winapi::sh_get_file_info(pp.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_))
::boost::winapi::sh_get_file_info(pp_ext.native().c_str(), 0, 0, 0, ::boost::winapi::SHGFI_EXETYPE_))
{
return pp;
return pp_ext;
}
}
}

View File

@@ -44,7 +44,7 @@ struct const_entry
bool operator()(char c) const {return c == api::env_seperator<char> ();}
} s;
boost::split(data, _data, s);
return std::move(data);
return data;
}
string_type to_string() const
{

View File

@@ -340,8 +340,9 @@ public:
basic_ipstream& operator=(basic_ipstream && lhs)
{
std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
_buf = std::move(lhs);
_buf = std::move(lhs._buf);
std::basic_istream<CharT, Traits>::rdbuf(&_buf);
return *this;
};
///Move assignment of a pipe.
basic_ipstream& operator=(pipe_type && p)
@@ -366,7 +367,7 @@ public:
///Get a rvalue reference to the pipe. Qualified as rvalue.
pipe_type && pipe() && {return std::move(_buf).pipe();}
///Check if the pipe is open
bool is_open() const {return _buf->is_open();}
bool is_open() const {return _buf.is_open();}
///Open a new pipe
void open()
@@ -448,8 +449,9 @@ public:
basic_opstream& operator=(basic_opstream && lhs)
{
std::basic_ostream<CharT, Traits>::operator=(std::move(lhs));
_buf = std::move(lhs);
_buf = std::move(lhs._buf);
std::basic_ostream<CharT, Traits>::rdbuf(&_buf);
return *this;
};
///Move assignment of a pipe.
@@ -556,8 +558,9 @@ public:
basic_pstream& operator=(basic_pstream && lhs)
{
std::basic_istream<CharT, Traits>::operator=(std::move(lhs));
_buf = std::move(lhs);
_buf = std::move(lhs._buf);
std::basic_iostream<CharT, Traits>::rdbuf(&_buf);
return *this;
};
///Move assignment of a pipe.
basic_pstream& operator=(pipe_type && p)

View File

@@ -73,5 +73,5 @@ after_test:
on_success:
on_failure:
on_finish:
- curl -s https://report.ci/upload.py | python - --name "Windows test run" --root_dir=%BOOST%/libs/%PROJECT_TO_TEST% --framework boost
- curl -s https://report.ci/upload.py | python - --name "Windows test run" --root_dir=%BOOST%

View File

@@ -96,8 +96,13 @@ BOOST_AUTO_TEST_CASE(move_pipe)
bp::async_pipe ap{ios};
BOOST_TEST_CHECKPOINT("First move");
bp::async_pipe ap2{std::move(ap)};
#if defined(BOOST_WINDOWS_API)
BOOST_CHECK_EQUAL(ap.native_source(), ::boost::winapi::INVALID_HANDLE_VALUE_);
BOOST_CHECK_EQUAL(ap.native_sink (), ::boost::winapi::INVALID_HANDLE_VALUE_);
#elif defined(BOOST_POSIX_API)
BOOST_CHECK_EQUAL(ap.native_source(), -1);
BOOST_CHECK_EQUAL(ap.native_sink (), -1);
#endif
BOOST_TEST_CHECKPOINT("Second move");
ap = std::move(ap2);

View File

@@ -118,6 +118,29 @@ BOOST_AUTO_TEST_CASE(compare, *boost::unit_test::timeout(5))
BOOST_TEST_PASSPOINT();
}
BOOST_AUTO_TEST_CASE(wcompare, *boost::unit_test::timeout(5))
{
auto nat = boost::this_process::wenvironment();
bp::wenvironment env = nat;
{
BOOST_CHECK_EQUAL(nat.size(), env.size());
auto ni = nat.begin();
auto ei = env.begin();
while ((ni != nat.end()) &&(ei != env.end()))
{
BOOST_CHECK_EQUAL(ni->get_name(), ei->get_name());
BOOST_CHECK_EQUAL(ni->to_string(), ei->to_string());
ni++; ei++;
}
}
BOOST_TEST_PASSPOINT();
env.clear();
BOOST_TEST_PASSPOINT();
}
BOOST_AUTO_TEST_CASE(insert_remove, *boost::unit_test::timeout(5))
{
bp::environment env(boost::this_process::environment());

View File

@@ -102,6 +102,110 @@ BOOST_AUTO_TEST_CASE(stream, *boost::unit_test::timeout(2))
BOOST_CHECK_EQUAL(i, j);
}
BOOST_AUTO_TEST_CASE(stream_move, *boost::unit_test::timeout(2))
{
bp::pipe pipe;
bp::pstream os(pipe);
bp::ipstream is(pipe);
int i = 42, j = 0, k = 0;
os << i << std::endl;
os << std::endl;
is >> j;
BOOST_CHECK_EQUAL(i, j);
bp::pstream os2 = std::move(os);
bp::ipstream is2 = std::move(is);
os2 << i << std::endl;
os2 << std::endl;
is2 >> k;
BOOST_CHECK_EQUAL(i, k);
}
BOOST_AUTO_TEST_CASE(ostream_move, *boost::unit_test::timeout(2))
{
bp::pipe pipe;
bp::opstream os(pipe);
bp::ipstream is(pipe);
int i = 42, j = 0, k = 0;
os << i << std::endl;
os << std::endl;
is >> j;
BOOST_CHECK_EQUAL(i, j);
bp::opstream os2 = std::move(os);
bp::ipstream is2 = std::move(is);
os2 << i << std::endl;
os2 << std::endl;
is2 >> k;
BOOST_CHECK_EQUAL(i, k);
}
BOOST_AUTO_TEST_CASE(stream_move_assignment, *boost::unit_test::timeout(2))
{
bp::pipe pipe;
bp::pstream os(pipe);
bp::ipstream is(pipe);
int i = 42, j = 0, k = 0;
os << i << std::endl;
os << std::endl;
is >> j;
BOOST_CHECK_EQUAL(i, j);
bp::pstream os2;
os2 = std::move(os);
bp::ipstream is2;
is2 = std::move(is);
os2 << i << std::endl;
os2 << std::endl;
is2 >> k;
BOOST_CHECK_EQUAL(i, k);
}
BOOST_AUTO_TEST_CASE(ostream_move_assignment, *boost::unit_test::timeout(2))
{
bp::pipe pipe;
bp::opstream os(pipe);
bp::ipstream is(pipe);
int i = 42, j = 0, k = 0;
os << i << std::endl;
os << std::endl;
is >> j;
BOOST_CHECK_EQUAL(i, j);
bp::opstream os2;
os2 = std::move(os);
bp::ipstream is2;
is2 = std::move(is);
os2 << i << std::endl;
os2 << std::endl;
is2 >> k;
BOOST_CHECK_EQUAL(i, k);
}
BOOST_AUTO_TEST_CASE(stream_line, *boost::unit_test::timeout(2))
{
@@ -268,4 +372,4 @@ BOOST_AUTO_TEST_CASE(stream_close_scope, *boost::unit_test::timeout(5))
}
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_SUITE_END();