mirror of
https://github.com/boostorg/process.git
synced 2026-01-19 04:22:15 +00:00
pty windows build fixes.
This commit is contained in:
@@ -58,7 +58,7 @@ class basic_pty
|
||||
template<typename Arg>
|
||||
handle_t_(Arg && arg) : rm{arg} {}
|
||||
|
||||
bool is_open() {return rm.is_open();}
|
||||
bool is_open() const {return rm.is_open();}
|
||||
};
|
||||
|
||||
handle_t_ handle_;
|
||||
@@ -600,10 +600,10 @@ class basic_pty
|
||||
this->close(ec);
|
||||
}
|
||||
#else
|
||||
net::connect_pipe(handle_.rm, handle_.ws, ec);
|
||||
net::connect_pipe(handle_.rm, handle_.ws, ec); // output
|
||||
if (!ec)
|
||||
{
|
||||
net::connect_pipe(handle_.wm, handle_.rs, ec);
|
||||
net::connect_pipe(handle_.rs, handle_.wm, ec); // input
|
||||
if (ec)
|
||||
handle_.rm.close(ec);
|
||||
}
|
||||
@@ -698,10 +698,14 @@ class basic_pty
|
||||
{
|
||||
error_code ec;
|
||||
if (!is_open())
|
||||
open(ec);
|
||||
open(console_size_t{80, 24}, ec);
|
||||
|
||||
auto &si = launcher.startup_info;
|
||||
|
||||
launcher.startup_info.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
// https://github.com/microsoft/terminal/issues/11276
|
||||
launcher.startup_info.StartupInfo.hStdOutput = NULL;
|
||||
launcher.startup_info.StartupInfo.hStdError = NULL;
|
||||
launcher.startup_info.StartupInfo.hStdInput = NULL;
|
||||
size_t bytes_required;
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &bytes_required);
|
||||
si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, bytes_required);
|
||||
|
||||
@@ -207,7 +207,7 @@ struct basic_stream
|
||||
}
|
||||
|
||||
/// Get the executor associated with the object.
|
||||
const executor_type& get_executor() noexcept
|
||||
executor_type get_executor() noexcept
|
||||
{
|
||||
return handle_.get_executor();
|
||||
}
|
||||
@@ -390,7 +390,7 @@ struct basic_stream
|
||||
struct ::termios t;
|
||||
return !tcgetattr(handle_.native_handle(), &t);
|
||||
#else
|
||||
return handle_.index() == 0u;
|
||||
return handle_.object.is_open();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ struct basic_stream
|
||||
else
|
||||
mode &= ~ENABLE_ECHO_INPUT;
|
||||
|
||||
if (!ec && SetConsoleMode(handle_.native_handle(), mode))
|
||||
if (!ec && !SetConsoleMode(handle_.native_handle(), mode))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
#endif
|
||||
}
|
||||
@@ -484,11 +484,11 @@ struct basic_stream
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
if (enable)
|
||||
mode |= ENABLE_LINE_INPUT;
|
||||
mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT ;
|
||||
else
|
||||
mode &= ~ENABLE_LINE_INPUT;
|
||||
mode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT );
|
||||
|
||||
if (!ec && SetConsoleMode(handle_.native_handle(), mode))
|
||||
if (!ec && !SetConsoleMode(handle_.native_handle(), mode))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
#endif
|
||||
}
|
||||
@@ -561,24 +561,26 @@ struct basic_stream
|
||||
{
|
||||
if (!this_->is_pty())
|
||||
{
|
||||
auto e = net::get_associated_immediate_executor(self, this_->sig_winch_.get_executor());
|
||||
auto e = net::get_associated_immediate_executor(self, this_->handle_.object.get_executor());
|
||||
return net::dispatch(e, net::append(std::move(self), net::error::operation_not_supported));
|
||||
}
|
||||
buf = this_->handle_.cs_buf_;
|
||||
this_->handle_.trigger_size_.async_wait(std::move(self));
|
||||
this_->async_wait(std::move(self));
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self && self, error_code ec)
|
||||
{
|
||||
if (ec == net::error::operation_aborted
|
||||
&& !self.get_cancellation_state().cancelled()
|
||||
&& buf != this_->handle_.cs_buf_)
|
||||
ec.clear();
|
||||
|
||||
if (this_->handle_.trigger_size_.expiry() == std::chrono::steady_clock::time_point::min())
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::broken_pipe);
|
||||
|
||||
if (!ec)
|
||||
{
|
||||
CONSOLE_SCREEN_BUFFER_INFO bi;
|
||||
if (::GetConsoleScreenBufferInfo(this_->handle_.object.native_handle(), &bi))
|
||||
{
|
||||
this_->handle_.cs_buf_.columns = bi.dwSize.X;
|
||||
this_->handle_.cs_buf_.rows = bi.dwSize.Y;
|
||||
}
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
}
|
||||
|
||||
self.complete(ec, this_->handle_.cs_buf_);
|
||||
}
|
||||
@@ -600,7 +602,7 @@ struct basic_stream
|
||||
async_wait_for_size_change_op_{this}, handler, handle_))
|
||||
{
|
||||
return net::async_compose<WaitHandler, void (error_code, console_size_t)>(
|
||||
async_wait_for_size_change_op_{this}, handler, get_executor());
|
||||
async_wait_for_size_change_op_{this}, handler, handle_);
|
||||
}
|
||||
|
||||
/// Wait for the stream to become ready to read.
|
||||
@@ -710,9 +712,9 @@ struct basic_stream
|
||||
auto async_wait(WaitToken&& token = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(this->handle_.async_wait(
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
net::posix::descriptor_base::wait_read, std::declval<WaitToken&&>()
|
||||
net::posix::descriptor_base::wait_read,
|
||||
#endif
|
||||
))
|
||||
std::declval<WaitToken&&>()))
|
||||
{
|
||||
return this->handle_.async_wait(
|
||||
#if defined(BOOST_PROCESS_V2_POSIX)
|
||||
@@ -836,11 +838,11 @@ struct basic_stream
|
||||
* @li @c cancellation_type::total
|
||||
*/
|
||||
template <typename MutableBufferSequence,
|
||||
BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, std::size_t)) ReadToken =
|
||||
BOOST_PROCESS_V2_COMPLETION_TOKEN_FOR(void (error_code, std::size_t)) ReadToken =
|
||||
net::default_completion_token_t<executor_type>>
|
||||
auto async_read_some(const MutableBufferSequence& buffers,
|
||||
ReadToken&& token = net::default_completion_token_t<executor_type>())
|
||||
-> decltype(this->handle_.async_read_some(buffers, std::forward<ReadToken>(token)))
|
||||
-> decltype(this->handle_.async_read_some(buffers, std::forward<ReadToken>(token)))
|
||||
{
|
||||
return this->handle_.async_read_some(buffers, std::forward<ReadToken>(token));
|
||||
}
|
||||
@@ -975,11 +977,11 @@ basic_stream<Executor> open_stdin(Executor exec, bool duplicate, error_code & ec
|
||||
typename basic_stream<Executor>::native_handle_type handle;
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (!duplicate)
|
||||
handle = GetStdHandle(STDIN_FILENO);
|
||||
handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
else if (
|
||||
!DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
GetStdHandle(STDIN_FILENO),
|
||||
GetStdHandle(STD_INPUT_HANDLE),
|
||||
GetCurrentProcess(),
|
||||
&handle,
|
||||
0u,
|
||||
@@ -1000,11 +1002,11 @@ basic_stream<Executor> open_stdout(Executor exec, bool duplicate, error_code & e
|
||||
typename basic_stream<Executor>::native_handle_type handle;
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (!duplicate)
|
||||
handle = GetStdHandle(STDOUT_FILENO);
|
||||
handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
else if (
|
||||
!DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
GetStdHandle(STDOUT_FILENO),
|
||||
GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
GetCurrentProcess(),
|
||||
&handle,
|
||||
0u,
|
||||
@@ -1025,11 +1027,11 @@ basic_stream<Executor> open_stderr(Executor exec, bool duplicate, error_code & e
|
||||
typename basic_stream<Executor>::native_handle_type handle;
|
||||
#if defined(BOOST_WINDOWS_API)
|
||||
if (!duplicate)
|
||||
handle = GetStdHandle(STDERR_FILENO);
|
||||
handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
else if (
|
||||
!DuplicateHandle(
|
||||
GetCurrentProcess(),
|
||||
GetStdHandle(STDERR_FILENO),
|
||||
GetStdHandle(STD_ERROR_HANDLE),
|
||||
GetCurrentProcess(),
|
||||
&handle,
|
||||
0u,
|
||||
|
||||
@@ -43,7 +43,6 @@ struct basic_stream_handle
|
||||
{
|
||||
net::windows::basic_object_handle<Executor> object;
|
||||
net::windows::basic_stream_handle<Executor> stream;
|
||||
net::steady_timer trigger_size_{get_executor(), std::chrono::steady_clock::time_point::max()};
|
||||
v2::experimental::console_size_t cs_buf_{0u, 0u};
|
||||
|
||||
template<typename Arg>
|
||||
@@ -51,15 +50,17 @@ struct basic_stream_handle
|
||||
|
||||
template<typename Executor1>
|
||||
basic_stream_handle(basic_stream_handle<Executor1> &&lhs)
|
||||
: object(std::move(lhs.object)), stream(std::move(lhs.stream)), trigger_size_(std::move(lhs.trigger_size_)),
|
||||
cs_buf_(lhs.cs_buf_) {}
|
||||
: object(std::move(lhs.object)), stream(std::move(lhs.stream)), cs_buf_(lhs.cs_buf_) {}
|
||||
|
||||
Executor get_executor() noexcept { return object.get_executor(); }
|
||||
using executor_type = Executor;
|
||||
executor_type get_executor() noexcept { return object.get_executor(); }
|
||||
|
||||
|
||||
void assign(HANDLE h, error_code &ec)
|
||||
{
|
||||
if (GetFileType(h) == FILE_TYPE_CHAR) {
|
||||
assert(GetFileType(h) == FILE_TYPE_CHAR);
|
||||
if (GetFileType(h) == FILE_TYPE_CHAR)
|
||||
{
|
||||
stream.close(ec);
|
||||
object.assign(h, ec);
|
||||
DWORD flags;
|
||||
@@ -68,15 +69,25 @@ struct basic_stream_handle
|
||||
return;
|
||||
}
|
||||
|
||||
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
||||
|
||||
if (!::SetConsoleMode(h, flags) ||
|
||||
!::SetConsoleCP(CP_UTF8) ||
|
||||
!::SetConsoleOutputCP(CP_UTF8))
|
||||
if (!::SetConsoleMode(h, flags | ENABLE_VIRTUAL_TERMINAL_INPUT)) // probably output!
|
||||
if (!::SetConsoleMode(h, flags | ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING ))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
if (!::SetConsoleCP(CP_UTF8))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
if (!::SetConsoleOutputCP(CP_UTF8))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
|
||||
trigger_size_.expires_at(std::chrono::steady_clock::time_point::max());
|
||||
} else {
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO bi;
|
||||
if (::GetConsoleScreenBufferInfo(h, &bi))
|
||||
{
|
||||
cs_buf_.columns = bi.dwSize.X;
|
||||
cs_buf_.rows = bi.dwSize.Y;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
object.close(ec);
|
||||
stream.assign(h, ec);
|
||||
}
|
||||
@@ -94,14 +105,12 @@ struct basic_stream_handle
|
||||
{
|
||||
object.close(ec);
|
||||
stream.close(ec);
|
||||
trigger_size_.expires_at(std::chrono::steady_clock::time_point::min());
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
object.close();
|
||||
stream.close();
|
||||
trigger_size_.expires_at(std::chrono::steady_clock::time_point::min());
|
||||
}
|
||||
|
||||
HANDLE native_handle()
|
||||
@@ -178,10 +187,13 @@ struct basic_stream_handle
|
||||
if (stream.is_open())
|
||||
return stream.read_some(mbs, ec);
|
||||
|
||||
net::mutable_buffer buf;
|
||||
|
||||
asio::mutable_buffer buf;
|
||||
|
||||
for (auto itr = net::buffer_sequence_begin(mbs);
|
||||
itr != net::buffer_sequence_end(mbs); itr++)
|
||||
if (itr->size() > 0) {
|
||||
if (itr->size() > 0)
|
||||
{
|
||||
buf = *itr;
|
||||
break;
|
||||
}
|
||||
@@ -189,43 +201,16 @@ struct basic_stream_handle
|
||||
if (buf.size() == 0u)
|
||||
return 0u;
|
||||
|
||||
try_again:
|
||||
INPUT_RECORD in_buffer[8092];
|
||||
DWORD sz = buf.size(), read_size = 0u; //
|
||||
if (!PeekConsoleInputW(object.native_handle(), in_buffer, sz, &read_size)) {
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return 0u;
|
||||
}
|
||||
|
||||
auto begin = in_buffer,
|
||||
end = in_buffer + read_size;
|
||||
|
||||
DWORD keys = 0u;
|
||||
for (auto itr = begin; itr != end; itr++) {
|
||||
if (itr->EventType == KEY_EVENT
|
||||
&& itr->Event.KeyEvent.bKeyDown)
|
||||
keys += itr->Event.KeyEvent.wRepeatCount;
|
||||
// not handling resize here: don't mix sync & async apis.
|
||||
}
|
||||
|
||||
if (keys == 0u) {
|
||||
// read all we just peeked
|
||||
if (!::ReadConsoleW(object.native_handle(), in_buffer, read_size, sz)) {
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return 0u;
|
||||
}
|
||||
|
||||
goto try_again; // never read zero
|
||||
}
|
||||
|
||||
read_size = 0u;
|
||||
if (!ReadFile(object.native_handle(), buf.data(), keys, &read_size, NULL)) {
|
||||
DWORD read_size = 0u;
|
||||
if (!::ReadFile(object.native_handle(), buf.data(), buf.size(), &read_size, NULL))
|
||||
{
|
||||
const DWORD last_error = ::GetLastError();
|
||||
if (ERROR_MORE_DATA == last_error)
|
||||
if (ERROR_END_OF_MEDIA == last_error)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::eof);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, last_error, system_category());
|
||||
}
|
||||
|
||||
return static_cast<std::size_t>(read_size);
|
||||
}
|
||||
|
||||
@@ -239,7 +224,7 @@ struct basic_stream_handle
|
||||
void operator()(Self &&self)
|
||||
{
|
||||
if (this_->stream.is_open())
|
||||
return this_->stream.async_reasd_some(buffer, std::move(self));
|
||||
return this_->stream.async_read_some(buffer, std::move(self));
|
||||
|
||||
this_->async_wait(std::move(self));
|
||||
}
|
||||
@@ -247,10 +232,12 @@ struct basic_stream_handle
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec)
|
||||
{
|
||||
net::mutable_buffer buf;
|
||||
asio::mutable_buffer buf;
|
||||
|
||||
for (auto itr = net::buffer_sequence_begin(buffer);
|
||||
itr != net::buffer_sequence_end(buffer); itr++)
|
||||
if (itr->size() > 0) {
|
||||
if (itr->size() > 0)
|
||||
{
|
||||
buf = *itr;
|
||||
break;
|
||||
}
|
||||
@@ -258,50 +245,56 @@ struct basic_stream_handle
|
||||
if (buf.size() == 0u)
|
||||
return self.complete(error_code{}, 0u);
|
||||
|
||||
WINDOW_BUFFER_SIZE_RECORD *window_change = nullptr;
|
||||
try_again:
|
||||
|
||||
INPUT_RECORD in_buffer[8092];
|
||||
DWORD sz = buf.size(), read_size = 0u; //
|
||||
if (!PeekConsoleInputW(this_->object.native_handle(), in_buffer, sz, &read_size)) {
|
||||
DWORD read_size = 0u;
|
||||
if (!::PeekConsoleInputW(this_->object.native_handle(), in_buffer, 8092, &read_size))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return self.complete(ec, 0u);
|
||||
}
|
||||
|
||||
auto begin = in_buffer,
|
||||
end = in_buffer + read_size;
|
||||
end = in_buffer + read_size;
|
||||
|
||||
DWORD keys = 0u;
|
||||
|
||||
for (auto itr = begin; itr != end; itr++) {
|
||||
if (itr->EventType == KEY_EVENT
|
||||
&& itr->Event.KeyEvent.bKeyDown)
|
||||
std::size_t keys = 0u;
|
||||
bool has_cr = false;
|
||||
for (auto itr = begin; itr != end; itr++)
|
||||
{
|
||||
if (itr->EventType == KEY_EVENT)
|
||||
{
|
||||
keys += itr->Event.KeyEvent.wRepeatCount;
|
||||
else if (itr->EventType == WINDOW_BUFFER_SIZE_EVENT)
|
||||
window_change = &itr->Event.WindowBufferSizeEvent;
|
||||
has_cr |= itr->Event.KeyEvent.uChar.AsciiChar == '\r';
|
||||
}
|
||||
}
|
||||
|
||||
if (keys == 0u) {
|
||||
// read all we just peeked
|
||||
if (!::ReadConsoleW(this_->object.native_handle(), in_buffer, read_size, sz)) {
|
||||
if (keys == 0u)
|
||||
{
|
||||
if (!::FlushConsoleInputBuffer(this_->object.native_handle()))
|
||||
{
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return self.complete(ec, 0u);
|
||||
}
|
||||
|
||||
goto try_again; // never read zero
|
||||
else
|
||||
return this_->async_wait(std::move(self));
|
||||
}
|
||||
|
||||
if (window_change) //
|
||||
if (!has_cr)
|
||||
{
|
||||
this_->cs_buf_.columns = window_change->dwSize.X;
|
||||
this_->cs_buf_.rows = window_change->dwSize.Y;
|
||||
this_->trigger_size_.cancel();
|
||||
DWORD mode = 0;
|
||||
if (!::GetConsoleMode(this_->object.native_handle(), &mode))
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
else if ((mode & ENABLE_LINE_INPUT) != 0)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::would_block); // line mode would block on windows
|
||||
}
|
||||
if (ec)
|
||||
return self.complete(ec, 0u);
|
||||
|
||||
DWORD to_read = (std::min)(keys, buf.size());
|
||||
|
||||
read_size = 0u;
|
||||
if (!ReadFile(this_->object.native_handle(), buf.data(), keys, &read_size, NULL)) {
|
||||
if (!ReadFile(this_->object.native_handle(), buf.data(), to_read, &read_size, NULL))
|
||||
{
|
||||
const DWORD last_error = ::GetLastError();
|
||||
if (ERROR_MORE_DATA == last_error)
|
||||
if (ERROR_END_OF_MEDIA == last_error)
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::eof);
|
||||
else
|
||||
BOOST_PROCESS_V2_ASSIGN_EC(ec, last_error, system_category());
|
||||
@@ -311,22 +304,22 @@ struct basic_stream_handle
|
||||
}
|
||||
|
||||
template<typename Self>
|
||||
void operator()(Self &&self, error_code ec, std::size_t n)
|
||||
void operator()(Self &&self, error_code ec, std::size_t n_)
|
||||
{
|
||||
self.complete(ec, n);
|
||||
self.complete(ec, n_);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename MutableBuffer, typename CompletionToken>
|
||||
auto async_read_some(const MutableBuffer &buffer, CompletionToken &&token)
|
||||
-> decltype(boost::asio::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
boost::asio::composed(async_read_some_op<MutableBuffer>{this, buffer}, socket), token))
|
||||
{
|
||||
return boost::asio::async_initiate<CompletionToken,
|
||||
-> decltype(net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
boost::asio::composed(async_read_some_op<MutableBuffer>{this, buffer}, socket), token);
|
||||
net::composed(async_read_some_op<MutableBuffer>{this, buffer}, stream), token))
|
||||
{
|
||||
return net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
net::composed(async_read_some_op<MutableBuffer>{this, buffer}, stream), token);
|
||||
}
|
||||
|
||||
template<typename ConstBufferSequence>
|
||||
@@ -335,10 +328,11 @@ struct basic_stream_handle
|
||||
if (stream.is_open())
|
||||
return stream.write_some(cbs, ec);
|
||||
|
||||
net::mutable_buffer buf;
|
||||
net::const_buffer buf;
|
||||
for (auto itr = net::buffer_sequence_begin(cbs);
|
||||
itr != net::buffer_sequence_end(cbs); itr++)
|
||||
if (itr->size() > 0) {
|
||||
if (itr->size() > 0)
|
||||
{
|
||||
buf = *itr;
|
||||
break;
|
||||
}
|
||||
@@ -347,9 +341,8 @@ struct basic_stream_handle
|
||||
return 0u;
|
||||
|
||||
// get one screen size, that's how much we'll write
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFOEX bi;
|
||||
if (!GetConsoleScreenBufferInfoEx(object.native_handle(), &bi)) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO bi;
|
||||
if (!GetConsoleScreenBufferInfo(object.native_handle(), &bi)) {
|
||||
BOOST_PROCESS_V2_ASSIGN_LAST_ERROR(ec);
|
||||
return 0u;
|
||||
}
|
||||
@@ -378,11 +371,23 @@ struct basic_stream_handle
|
||||
error_code ec;
|
||||
auto n = this_->write_some(buffer, ec);
|
||||
auto exec = net::get_associated_immediate_executor(
|
||||
handler, this_->sig_winch_.get_executor());
|
||||
handler, this_->object.get_executor());
|
||||
net::dispatch(exec, net::append(std::move(handler), ec, n));
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ConstBufferSequence, typename CompletionToken>
|
||||
auto async_write_some(const ConstBufferSequence & buffer, CompletionToken && token)
|
||||
-> decltype(net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
async_write_op<ConstBufferSequence>{this, buffer}, token))
|
||||
{
|
||||
return net::async_initiate<CompletionToken,
|
||||
void(boost::system::error_code, std::size_t)>(
|
||||
async_write_op<ConstBufferSequence>{this, buffer}, token);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
#include <boost/process/v2/experimental/pty.hpp>
|
||||
#include <boost/process/v2/process.hpp>
|
||||
|
||||
@@ -37,12 +39,12 @@ BOOST_AUTO_TEST_CASE(sync_plain)
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
std::string read_buffer;
|
||||
read_buffer.resize(64);
|
||||
read_buffer.resize(128);
|
||||
auto rb = net::buffer(read_buffer);
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l1)), 5);
|
||||
auto n = pt.read_some(rb);
|
||||
BOOST_CHECK_EQUAL(n, 5); rb += n;
|
||||
BOOST_CHECK_MESSAGE(n == 5, read_buffer.substr(0, n)); rb += n;
|
||||
|
||||
BOOST_CHECK_EQUAL(pt.write_some(net::buffer(l2)), 2);
|
||||
BOOST_CHECK_EQUAL(n = pt.read_some(rb), 2); rb += n;
|
||||
@@ -77,6 +79,8 @@ BOOST_AUTO_TEST_CASE(async_plain)
|
||||
bp2::experimental::pty &pt;
|
||||
bp2::process &proc;
|
||||
|
||||
op(bp2::experimental::pty &pt, bp2::process &proc) : pt(pt), proc(proc) {}
|
||||
|
||||
std::string read_buffer = std::string(64, ' ');
|
||||
net::mutable_buffer rb = net::buffer(read_buffer);
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
@@ -115,7 +119,7 @@ BOOST_AUTO_TEST_CASE(async_plain)
|
||||
}
|
||||
};
|
||||
|
||||
op{{}, pt, proc}({}, 0u);
|
||||
op{pt, proc}({}, 0u);
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
@@ -169,7 +173,6 @@ BOOST_AUTO_TEST_CASE(async_echo)
|
||||
bp2::experimental::pty pt{ctx};
|
||||
bp2::process proc(ctx, pth, {"--async", "--echo"}, pt);
|
||||
|
||||
|
||||
char buf[4];
|
||||
net::read(pt, net::buffer(buf));
|
||||
|
||||
@@ -179,6 +182,8 @@ BOOST_AUTO_TEST_CASE(async_echo)
|
||||
bp2::experimental::pty &pt;
|
||||
bp2::process &proc;
|
||||
|
||||
op(bp2::experimental::pty &pt, bp2::process &proc) : pt(pt), proc(proc) {}
|
||||
|
||||
std::string read_buffer = std::string(64, ' ');
|
||||
net::mutable_buffer rb = net::buffer(read_buffer);
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
@@ -217,7 +222,7 @@ BOOST_AUTO_TEST_CASE(async_echo)
|
||||
}
|
||||
};
|
||||
|
||||
op{{}, pt, proc}({}, 0u);
|
||||
op{pt, proc}({}, 0u);
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
@@ -252,6 +257,8 @@ BOOST_AUTO_TEST_CASE(async_line)
|
||||
bp2::experimental::pty &pt;
|
||||
std::size_t & read;
|
||||
|
||||
op(bp2::experimental::pty &pt, std::size_t & read) : pt(pt), read(read) {}
|
||||
|
||||
std::string l1 = "Hello", l2 = ", ", l3 = "World!", l4 = "\n";
|
||||
|
||||
|
||||
@@ -276,7 +283,7 @@ BOOST_AUTO_TEST_CASE(async_line)
|
||||
}
|
||||
};
|
||||
|
||||
op{{}, pt, read}({}, 0u);
|
||||
op{pt, read}({}, 0u);
|
||||
ctx.run();
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ struct async_op : net::coroutine
|
||||
{
|
||||
bp::experimental::basic_stream<net::io_context::executor_type> &in, &out;
|
||||
|
||||
async_op(bp::experimental::basic_stream<net::io_context::executor_type> &in,
|
||||
bp::experimental::basic_stream<net::io_context::executor_type> &out) : in(in), out(out) {}
|
||||
void operator()(bp::error_code ec = {}, std::size_t n = {})
|
||||
{
|
||||
if (ec)
|
||||
@@ -46,13 +48,14 @@ struct async_op : net::coroutine
|
||||
};
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
try
|
||||
{
|
||||
net::io_context ctx;
|
||||
|
||||
auto in = bp::experimental::open_stdin(ctx.get_executor());
|
||||
assert(in.is_pty());
|
||||
assert(in.echo());
|
||||
assert(in.line());
|
||||
//assert(in.echo());
|
||||
//assert(in.line());
|
||||
|
||||
std::vector<std::string> args{argv + 1, argv + argc};
|
||||
|
||||
@@ -64,8 +67,6 @@ int main(int argc, char * argv[])
|
||||
|
||||
auto out = stder ? bp::experimental::open_stderr(ctx.get_executor())
|
||||
: bp::experimental::open_stdout(ctx.get_executor());
|
||||
|
||||
|
||||
in.set_echo(echo);
|
||||
in.set_line(line);
|
||||
|
||||
@@ -92,7 +93,7 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
else if (async)
|
||||
{
|
||||
net::post(ctx, async_op{{}, in, out});
|
||||
net::post(ctx, async_op{in, out});
|
||||
ctx.run();
|
||||
}
|
||||
else
|
||||
@@ -110,4 +111,9 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
|
||||
return 0u;
|
||||
}
|
||||
catch(boost::system::system_error & se)
|
||||
{
|
||||
fprintf(stderr, "Pty-Target exception: %s(%d): %s\n", se.code().location().file_name(), se.code().location().line(), se.what());
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user