aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2016-11-03 00:44:53 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2016-11-03 13:47:43 +0300
commit7ce74ce206065c3af0035583330b3c773086f21c (patch)
treefc0fb1d9bd0037299f12a27f1f38ac5056634568
parentcc8a2a1517cc3c55bdeb066a038868fb8c7f04d6 (diff)
Invent auto_fd, make use of it in fdstreams and process
-rw-r--r--butl/fdstream121
-rw-r--r--butl/fdstream.cxx63
-rw-r--r--butl/fdstream.ixx64
-rw-r--r--butl/optional4
-rw-r--r--butl/pager.cxx5
-rw-r--r--butl/process14
-rw-r--r--butl/process.cxx92
-rw-r--r--butl/process.ixx12
-rw-r--r--tests/fdstream/driver.cxx17
-rw-r--r--tests/process/driver.cxx25
10 files changed, 209 insertions, 208 deletions
diff --git a/butl/fdstream b/butl/fdstream
index 2d7fae5..9c7274d 100644
--- a/butl/fdstream
+++ b/butl/fdstream
@@ -8,6 +8,7 @@
#include <string>
#include <istream>
#include <ostream>
+#include <utility> // move()
#include <cstdint> // uint16_t
#include <butl/export>
@@ -17,6 +18,45 @@
namespace butl
{
+ // RAII type for file descriptors. Note that failure to close the descriptor
+ // is silently ignored by both the destructor and reset() (thought we could
+ // probably provide the close() function that throws).
+ //
+ // The descriptor can be negative. Such a descriptor is treated as unopened
+ // and is not closed.
+ //
+ struct nullfd_t {constexpr explicit nullfd_t (int) {}};
+ constexpr const nullfd_t nullfd (-1);
+
+ class auto_fd
+ {
+ public:
+ auto_fd (nullfd_t = nullfd): fd_ (-1) {}
+
+ explicit
+ auto_fd (int fd) noexcept: fd_ (fd) {}
+
+ auto_fd (auto_fd&& fd) noexcept: fd_ (fd.release ()) {}
+ auto_fd& operator= (auto_fd&&) noexcept;
+
+ auto_fd (const auto_fd&) = delete;
+ auto_fd& operator= (const auto_fd&) = delete;
+
+ ~auto_fd () noexcept {reset ();}
+
+ int
+ get () const noexcept {return fd_;}
+
+ int
+ release () noexcept;
+
+ void
+ reset (int fd = -1) noexcept;
+
+ private:
+ int fd_;
+ };
+
// An [io]fstream that can be initialized with a file descriptor in addition
// to a file name and that also by default enables exceptions on badbit and
// failbit. So instead of a dance like this:
@@ -41,31 +81,26 @@ namespace butl
// - after catching an exception caused by badbit the stream is no longer
// used
// - not movable, though can be easily supported
- // - passing to constructor -1 file descriptor is valid and results in the
- // creation of an unopened object
+ // - passing to constructor auto_fd with a negative file descriptor is valid
+ // and results in the creation of an unopened object
//
class LIBBUTL_EXPORT fdbuf: public std::basic_streambuf<char>
{
public:
- virtual
- ~fdbuf ();
fdbuf () = default;
- fdbuf (int fd) {if (fd != -1) open (fd);}
-
- fdbuf (const fdbuf&) = delete;
- fdbuf& operator= (const fdbuf&) = delete;
+ fdbuf (auto_fd&&);
void
close ();
void
- open (int fd);
+ open (auto_fd&&);
bool
- is_open () const {return fd_ != -1;}
+ is_open () const {return fd_.get () >= 0;}
int
- fd () const {return fd_;}
+ fd () const {return fd_.get ();}
public:
using int_type = std::basic_streambuf<char>::int_type;
@@ -101,7 +136,7 @@ namespace butl
save ();
private:
- int fd_ = -1;
+ auto_fd fd_;
char buf_[8192];
bool non_blocking_ = false;
};
@@ -164,8 +199,8 @@ namespace butl
{
protected:
fdstream_base () = default;
- fdstream_base (int fd): buf_ (fd) {}
- fdstream_base (int, fdstream_mode);
+ fdstream_base (auto_fd&& fd): buf_ (std::move (fd)) {}
+ fdstream_base (auto_fd&&, fdstream_mode);
public:
int
@@ -191,18 +226,13 @@ namespace butl
// iofdstream constructors and open() functions that take file path as a
// const std::string& or const char* may throw the invalid_path exception.
//
- // Passing -1 as a file descriptor is valid and results in the creation of
- // an unopened object.
+ // Passing auto_fd with a negative file descriptor is valid and results in
+ // the creation of an unopened object.
//
// Also note that open() and close() functions can be successfully called
// for an opened and unopened objects respectively. That is in contrast with
// iofstream that sets failbit in such cases.
//
- // @@ Need to make sure performance is on par with fstream on both
- // Linux and Windows.
- //
- // @@ Do we need to increase default buffer size? Make it customizable?
- // Wonder what it is in libstdc++ and MSVC?
// Note that ifdstream destructor will close an open file descriptor but
// will ignore any errors. To detect such errors, call close() explicitly.
@@ -219,8 +249,8 @@ namespace butl
// {
// // In case of exception, skip and close input after output.
// //
- // ifdstream is (pr.in_ofd, fdstream_mode::skip);
- // ofdstream os (pr.out_fd);
+ // ifdstream is (move (pr.in_ofd), fdstream_mode::skip);
+ // ofdstream os (move (pr.out_fd));
//
// // Write.
//
@@ -268,17 +298,14 @@ namespace butl
class LIBBUTL_EXPORT ifdstream: public fdstream_base, public std::istream
{
public:
- // Create an unopened object with iostate = badbit | failbit (we cannot
- // have the iostate as an argument since it clashes with int fd) To create
- // an unopened object with non-default exception mask one can do:
- //
- // ifdstream (-1, ...);
+ // Create an unopened object.
//
- ifdstream ();
+ explicit
+ ifdstream (iostate e = badbit | failbit);
explicit
- ifdstream (int fd, iostate e = badbit | failbit);
- ifdstream (int fd, fdstream_mode m, iostate e = badbit | failbit);
+ ifdstream (auto_fd&&, iostate e = badbit | failbit);
+ ifdstream (auto_fd&&, fdstream_mode m, iostate e = badbit | failbit);
explicit
ifdstream (const char*,
@@ -328,7 +355,7 @@ namespace butl
open (const path&, fdopen_mode);
void
- open (int fd) {buf_.open (fd); clear ();}
+ open (auto_fd&& fd) {buf_.open (std::move (fd)); clear ();}
void close ();
bool is_open () const {return buf_.is_open ();}
@@ -348,17 +375,14 @@ namespace butl
class LIBBUTL_EXPORT ofdstream: public fdstream_base, public std::ostream
{
public:
- // Create an unopened object with iostate = badbit | failbit (we cannot
- // have the iostate as an argument since it clashes with int fd). To create
- // an unopened object with non-default exception mask one can do:
- //
- // ofdstream (-1, ...);
+ // Create an unopened object.
//
- ofdstream ();
+ explicit
+ ofdstream (iostate e = badbit | failbit);
explicit
- ofdstream (int fd, iostate e = badbit | failbit);
- ofdstream (int fd, fdstream_mode m, iostate e = badbit | failbit);
+ ofdstream (auto_fd&&, iostate e = badbit | failbit);
+ ofdstream (auto_fd&&, fdstream_mode m, iostate e = badbit | failbit);
explicit
ofdstream (const char*,
@@ -408,7 +432,7 @@ namespace butl
open (const path&, fdopen_mode);
void
- open (int fd) {buf_.open (fd); clear ();}
+ open (auto_fd&& fd) {buf_.open (std::move (fd)); clear ();}
void close () {if (is_open ()) flush (); buf_.close ();}
bool is_open () const {return buf_.is_open ();}
@@ -432,8 +456,8 @@ namespace butl
LIBBUTL_EXPORT ifdstream&
getline (ifdstream&, std::string&, char delim = '\n');
- // Open a file returning the file descriptor on success and throwing
- // ios:failure otherwise.
+ // Open a file returning an auto_fd that holds its file descriptor on
+ // success and throwing ios::failure otherwise.
//
// The mode argument should have at least one of the in or out flags set.
// The append and truncate flags are meaningless in the absense of the out
@@ -448,21 +472,21 @@ namespace butl
// process' umask, so effective permissions are permissions & ~umask. On
// Windows permissions other than ru and wu are unlikelly to have effect.
//
- LIBBUTL_EXPORT int
+ LIBBUTL_EXPORT auto_fd
fdopen (const char*,
fdopen_mode,
permissions = permissions::ru | permissions::wu |
permissions::rg | permissions::wg |
permissions::ro | permissions::wo);
- LIBBUTL_EXPORT int
+ LIBBUTL_EXPORT auto_fd
fdopen (const std::string&,
fdopen_mode,
permissions = permissions::ru | permissions::wu |
permissions::rg | permissions::wg |
permissions::ro | permissions::wo);
- LIBBUTL_EXPORT int
+ LIBBUTL_EXPORT auto_fd
fdopen (const path&,
fdopen_mode,
permissions = permissions::ru | permissions::wu |
@@ -510,6 +534,11 @@ namespace butl
// closed. One difference, however, would be if you were to both write to
// and read from the descriptor.
//
+ // @@ You may have noticed that this interface doesn't match fdopen() (it
+ // does not throw and return int instead of auto_fd). The reason for this
+ // is process and its need to translate everything to process_error).
+ // Once we solve that we can clean this up as well.
+ //
#ifndef _WIN32
LIBBUTL_EXPORT int
fdnull () noexcept;
diff --git a/butl/fdstream.cxx b/butl/fdstream.cxx
index 109b041..dbd7767 100644
--- a/butl/fdstream.cxx
+++ b/butl/fdstream.cxx
@@ -71,19 +71,19 @@ namespace butl
// fdbuf
//
fdbuf::
- ~fdbuf ()
+ fdbuf (auto_fd&& fd)
{
- if (is_open ())
- fdclose (fd_); // Don't check for an error as not much we can do here.
+ if (fd.get () >= 0)
+ open (move (fd));
}
void fdbuf::
- open (int fd)
+ open (auto_fd&& fd)
{
close ();
#ifndef _WIN32
- int flags (fcntl (fd, F_GETFL));
+ int flags (fcntl (fd.get (), F_GETFL));
if (flags == -1)
throw_ios_failure (errno);
@@ -91,21 +91,22 @@ namespace butl
non_blocking_ = (flags & O_NONBLOCK) == O_NONBLOCK;
#endif
- fd_ = fd;
setg (buf_, buf_, buf_);
setp (buf_, buf_ + sizeof (buf_) - 1); // Keep space for overflow's char.
+
+ fd_ = move (fd);
}
void fdbuf::
close ()
{
- if (is_open ())
- {
- if (!fdclose (fd_))
- throw_ios_failure (errno);
-
- fd_ = -1;
- }
+ // Before we invented auto_fd into fdstreams we keept fdbuf opened on
+ // faulty close attempt. Now fdbuf is always closed by close() function.
+ // This semantics change seems to be the right one as there is no reason to
+ // expect fdclose() to succeed after it has already failed once.
+ //
+ if (is_open () && !fdclose (fd_.release ()))
+ throw_ios_failure (errno);
}
streamsize fdbuf::
@@ -122,7 +123,7 @@ namespace butl
#ifndef _WIN32
if (non_blocking_)
{
- ssize_t n (read (fd_, buf_, sizeof (buf_)));
+ ssize_t n (read (fd_.get (), buf_, sizeof (buf_)));
if (n == -1)
{
@@ -173,9 +174,9 @@ namespace butl
assert (!non_blocking_);
#ifndef _WIN32
- ssize_t n (read (fd_, buf_, sizeof (buf_)));
+ ssize_t n (read (fd_.get (), buf_, sizeof (buf_)));
#else
- int n (_read (fd_, buf_, sizeof (buf_)));
+ int n (_read (fd_.get (), buf_, sizeof (buf_)));
#endif
if (n == -1)
@@ -242,9 +243,9 @@ namespace butl
// expected). This is in contrast with VC's _write() and POSIX's write().
//
#ifndef _WIN32
- ssize_t m (write (fd_, buf_, n));
+ ssize_t m (write (fd_.get (), buf_, n));
#else
- int m (_write (fd_, buf_, n));
+ int m (_write (fd_.get (), buf_, n));
#endif
if (m == -1)
@@ -296,10 +297,10 @@ namespace butl
// Write both buffered and new data with a single system call.
//
iovec iov[2] = {{pbase (), bn}, {const_cast<char*> (s), n}};
- r = writev (fd_, iov, 2);
+ r = writev (fd_.get (), iov, 2);
}
else
- r = write (fd_, s, n);
+ r = write (fd_.get (), s, n);
if (r == -1)
throw_ios_failure (errno);
@@ -342,7 +343,7 @@ namespace butl
// Flush the buffer.
//
size_t wn (bn + an);
- int r (wn > 0 ? _write (fd_, buf_, wn) : 0);
+ int r (wn > 0 ? _write (fd_.get (), buf_, wn) : 0);
if (r == -1)
throw_ios_failure (errno);
@@ -378,7 +379,7 @@ namespace butl
// The data tail doesn't fit the buffer so write it to the file.
//
- r = _write (fd_, s, n);
+ r = _write (fd_.get (), s, n);
if (r == -1)
throw_ios_failure (errno);
@@ -393,15 +394,15 @@ namespace butl
return (m & flag) == flag;
}
- inline static int
- mode (int fd, fdstream_mode m)
+ inline static auto_fd
+ mode (auto_fd fd, fdstream_mode m)
{
- if (fd != -1 &&
+ if (fd.get () >= 0 &&
(flag (m, fdstream_mode::text) ||
flag (m, fdstream_mode::binary) ||
flag (m, fdstream_mode::blocking) ||
flag (m, fdstream_mode::non_blocking)))
- fdmode (fd, m);
+ fdmode (fd.get (), m);
return fd;
}
@@ -409,8 +410,8 @@ namespace butl
// fdstream_base
//
fdstream_base::
- fdstream_base (int fd, fdstream_mode m)
- : fdstream_base (mode (fd, m)) // Delegate.
+ fdstream_base (auto_fd&& fd, fdstream_mode m)
+ : fdstream_base (mode (move (fd), m)) // Delegate.
{
}
@@ -582,7 +583,7 @@ namespace butl
// Utility functions
//
- int
+ auto_fd
fdopen (const char* f, fdopen_mode m, permissions p)
{
mode_t pf (S_IREAD | S_IWRITE | S_IEXEC);
@@ -714,7 +715,7 @@ namespace butl
}
}
- return fd;
+ return auto_fd (fd);
}
#ifndef _WIN32
@@ -793,7 +794,7 @@ namespace butl
int
fdnull (bool temp) noexcept
{
- // No need to translate /r/n before sending it to void.
+ // No need to translate \r\n before sending it to void.
//
if (!temp)
return _sopen ("nul", _O_RDWR | _O_BINARY, _SH_DENYNO);
diff --git a/butl/fdstream.ixx b/butl/fdstream.ixx
index c7c329b..5d38d36 100644
--- a/butl/fdstream.ixx
+++ b/butl/fdstream.ixx
@@ -6,26 +6,51 @@
namespace butl
{
- // ifdstream
+ // auto_fd
//
- inline ifdstream::
- ifdstream ()
- : std::istream (&buf_)
+ inline auto_fd& auto_fd::
+ operator= (auto_fd&& fd) noexcept
+ {
+ reset (fd.release ());
+ return *this;
+ }
+
+ inline int auto_fd::
+ release () noexcept
{
- exceptions (badbit | failbit);
+ int r (fd_);
+ fd_ = -1;
+ return r;
}
+ inline void auto_fd::
+ reset (int fd) noexcept
+ {
+ if (fd_ >= 0)
+ fdclose (fd_); // Don't check for an error as not much we can do here.
+
+ fd_ = fd;
+ }
+
+ // ifdstream
+ //
inline ifdstream::
- ifdstream (int fd, iostate e)
- : fdstream_base (fd), std::istream (&buf_)
+ ifdstream (auto_fd&& fd, iostate e)
+ : fdstream_base (std::move (fd)), std::istream (&buf_)
{
assert (e & badbit);
exceptions (e);
}
inline ifdstream::
- ifdstream (int fd, fdstream_mode m, iostate e)
- : fdstream_base (fd, m),
+ ifdstream (iostate e)
+ : ifdstream (auto_fd (), e) // Delegate.
+ {
+ }
+
+ inline ifdstream::
+ ifdstream (auto_fd&& fd, fdstream_mode m, iostate e)
+ : fdstream_base (std::move (fd), m),
std::istream (&buf_),
skip_ ((m & fdstream_mode::skip) == fdstream_mode::skip)
{
@@ -84,23 +109,22 @@ namespace butl
// ofdstream
//
inline ofdstream::
- ofdstream ()
- : std::ostream (&buf_)
+ ofdstream (auto_fd&& fd, iostate e)
+ : fdstream_base (std::move (fd)), std::ostream (&buf_)
{
- exceptions (badbit | failbit);
+ assert (e & badbit);
+ exceptions (e);
}
inline ofdstream::
- ofdstream (int fd, iostate e)
- : fdstream_base (fd), std::ostream (&buf_)
+ ofdstream (iostate e)
+ : ofdstream (auto_fd (), e) // Delegate.
{
- assert (e & badbit);
- exceptions (e);
}
inline ofdstream::
- ofdstream (int fd, fdstream_mode m, iostate e)
- : fdstream_base (fd, m), std::ostream (&buf_)
+ ofdstream (auto_fd&& fd, fdstream_mode m, iostate e)
+ : fdstream_base (std::move (fd), m), std::ostream (&buf_)
{
assert (e & badbit);
exceptions (e);
@@ -156,13 +180,13 @@ namespace butl
// fdopen()
//
- inline int
+ inline auto_fd
fdopen (const std::string& f, fdopen_mode m, permissions p)
{
return fdopen (f.c_str (), m, p);
}
- inline int
+ inline auto_fd
fdopen (const path& f, fdopen_mode m, permissions p)
{
return fdopen (f.string (), m, p);
diff --git a/butl/optional b/butl/optional
index 0ae7e7b..21d686c 100644
--- a/butl/optional
+++ b/butl/optional
@@ -11,8 +11,8 @@ namespace butl
{
// Simple optional class template while waiting for std::optional.
//
- struct nullopt_t {constexpr nullopt_t (int) {}};
- constexpr const nullopt_t nullopt = 1;
+ struct nullopt_t {constexpr explicit nullopt_t (int) {}};
+ constexpr const nullopt_t nullopt (1);
template <typename T>
class optional
diff --git a/butl/pager.cxx b/butl/pager.cxx
index b154a5c..a03582c 100644
--- a/butl/pager.cxx
+++ b/butl/pager.cxx
@@ -15,6 +15,7 @@
#endif
#include <cstring> // strchr()
+#include <utility> // move()
#include <system_error>
#include <butl/fdstream> // fdclose()
@@ -134,13 +135,13 @@ namespace butl
bool r;
if (p_.try_wait (r))
{
- fdclose (p_.out_fd);
+ p_.out_fd.reset ();
if (pager != nullptr)
throw system_error (ECHILD, system_category ());
}
else
- os_.open (p_.out_fd);
+ os_.open (move (p_.out_fd));
}
catch (const process_error& e)
{
diff --git a/butl/process b/butl/process
index c69c306..e98e367 100644
--- a/butl/process
+++ b/butl/process
@@ -17,6 +17,7 @@
#include <butl/path>
#include <butl/export>
#include <butl/optional>
+#include <butl/fdstream> // auto_fd
namespace butl
{
@@ -134,7 +135,7 @@ namespace butl
// the child process. When reading in the text mode the sequence of 0xD,
// 0xA characters is translated into the single OxA character and 0x1A is
// interpreted as EOF. When writing in the text mode the OxA character is
- // translated into the 0xD, 0xA sequence. Use the _setmode() function to
+ // translated into the 0xD, 0xA sequence. Use the fdmode() function to
// change the mode, if required.
//
// Instead of passing -1, -2 or the default value, you can also pass your
@@ -216,8 +217,6 @@ namespace butl
// Create an empty or "already terminated" process. By default the
// termination status is abnormal but you can change that.
//
- // @@ Need to audit all calls (__attribute__((deprecated))).
- //
explicit
process (optional<status_type> status = nullopt);
@@ -295,9 +294,12 @@ namespace butl
handle_type handle;
optional<status_type> status; // Absence means terminated abnormally.
- int out_fd; // Write to this fd to send to the new process' stdin.
- int in_ofd; // Read from this fd to receive from the new process' stdout.
- int in_efd; // Read from this fd to receive from the new process' stderr.
+ // Use the following file descriptors to communicate with the new process's
+ // standard streams.
+ //
+ auto_fd out_fd; // Write to it to send to stdin.
+ auto_fd in_ofd; // Read from it to receive from stdout.
+ auto_fd in_efd; // Read from it to receive from stderr.
};
}
diff --git a/butl/process.cxx b/butl/process.cxx
index 3af42cf..d8b10be 100644
--- a/butl/process.cxx
+++ b/butl/process.cxx
@@ -37,10 +37,11 @@
#include <cassert>
#include <cstddef> // size_t
#include <cstring> // strlen(), strchr()
+#include <utility> // move()
#include <ostream>
#include <butl/utility> // casecmp()
-#include <butl/fdstream> // fdnull(), fdclose()
+#include <butl/fdstream> // fdnull()
using namespace std;
@@ -50,49 +51,6 @@ using namespace butl::win32;
namespace butl
{
- class auto_fd
- {
- public:
- explicit
- auto_fd (int fd = -1) noexcept: fd_ (fd) {}
-
- auto_fd (const auto_fd&) = delete;
- auto_fd& operator= (const auto_fd&) = delete;
-
- ~auto_fd () noexcept {reset ();}
-
- int
- get () const noexcept {return fd_;}
-
- int
- release () noexcept
- {
- int r (fd_);
- fd_ = -1;
- return r;
- }
-
- void
- reset (int fd = -1) noexcept
- {
- if (fd_ != -1)
- {
- bool r (fdclose (fd_));
-
- // The valid file descriptor that has no IO operations being
- // performed on it should close successfully, unless something is
- // severely damaged.
- //
- assert (r);
- }
-
- fd_ = fd;
- }
-
- private:
- int fd_;
- };
-
static process_path
path_search (const char*, const dir_path&);
@@ -158,6 +116,16 @@ namespace butl
} while (*p != nullptr);
}
+ process::
+ process (const char* cwd,
+ const process_path& pp, const char* args[],
+ process& in, int out, int err)
+ : process (cwd, pp, args, in.in_ofd.get (), out, err)
+ {
+ assert (in.in_ofd.get () != -1); // Should be a pipe.
+ in.in_ofd.reset (); // Close it on our side.
+ }
+
#ifndef _WIN32
static process_path
@@ -365,19 +333,9 @@ namespace butl
assert (handle != 0); // Shouldn't get here unless in the parent process.
- this->out_fd = out_fd[1].release ();
- this->in_ofd = in_ofd[0].release ();
- this->in_efd = in_efd[0].release ();
- }
-
- process::
- process (const char* cwd,
- const process_path& pp, const char* args[],
- process& in, int out, int err)
- : process (cwd, pp, args, in.in_ofd, out, err)
- {
- assert (in.in_ofd != -1); // Should be a pipe.
- close (in.in_ofd); // Close it on our side.
+ this->out_fd = move (out_fd[1]);
+ this->in_ofd = move (in_ofd[0]);
+ this->in_efd = move (in_efd[0]);
}
bool process::
@@ -849,13 +807,9 @@ namespace butl
return fd;
};
- auto_fd out_fd (in == -1 ? open_osfhandle (out_h[1]) : -1);
- auto_fd in_ofd (out == -1 ? open_osfhandle (in_oh[0]) : -1);
- auto_fd in_efd (err == -1 ? open_osfhandle (in_eh[0]) : -1);
-
- this->out_fd = out_fd.release ();
- this->in_ofd = in_ofd.release ();
- this->in_efd = in_efd.release ();
+ this->out_fd.reset (in == -1 ? open_osfhandle (out_h[1]) : -1);
+ this->in_ofd.reset (out == -1 ? open_osfhandle (in_oh[0]) : -1);
+ this->in_efd.reset (err == -1 ? open_osfhandle (in_eh[0]) : -1);
this->handle = process.release ();
@@ -864,16 +818,6 @@ namespace butl
assert (this->handle != 0 && this->handle != INVALID_HANDLE_VALUE);
}
- process::
- process (const char* cwd,
- const process_path& pp, const char* args[],
- process& in, int out, int err)
- : process (cwd, pp, args, in.in_ofd, out, err)
- {
- assert (in.in_ofd != -1); // Should be a pipe.
- _close (in.in_ofd); // Close it on our side.
- }
-
bool process::
wait (bool ie)
{
diff --git a/butl/process.ixx b/butl/process.ixx
index 6d4dd2f..1bc259c 100644
--- a/butl/process.ixx
+++ b/butl/process.ixx
@@ -139,9 +139,9 @@ namespace butl
process (process&& p)
: handle (p.handle),
status (p.status),
- out_fd (p.out_fd),
- in_ofd (p.in_ofd),
- in_efd (p.in_efd)
+ out_fd (std::move (p.out_fd)),
+ in_ofd (std::move (p.in_ofd)),
+ in_efd (std::move (p.in_efd))
{
p.handle = 0;
}
@@ -156,9 +156,9 @@ namespace butl
handle = p.handle;
status = std::move (p.status);
- out_fd = p.out_fd;
- in_ofd = p.in_ofd;
- in_efd = p.in_efd;
+ out_fd = std::move (p.out_fd);
+ in_ofd = std::move (p.in_ofd);
+ in_efd = std::move (p.in_efd);
p.handle = 0;
}
diff --git a/tests/fdstream/driver.cxx b/tests/fdstream/driver.cxx
index f77e2d5..4d72284 100644
--- a/tests/fdstream/driver.cxx
+++ b/tests/fdstream/driver.cxx
@@ -14,6 +14,7 @@
#include <cassert>
#include <sstream>
#include <fstream>
+#include <utility> // move()
#include <iostream>
#include <exception>
@@ -134,8 +135,8 @@ main (int argc, const char* argv[])
cout.flush ();
// @@ MINGW GCC 4.9 doesn't implement this_thread. If ifdstream
- // non-blocking read will ever be implemented use Win32 Sleep()
- // instead.
+ // non-blocking read will ever be implemented on Windows use Win32
+ // Sleep() instead.
//
#ifndef _WIN32
this_thread::sleep_for (chrono::milliseconds (50));
@@ -250,7 +251,7 @@ main (int argc, const char* argv[])
to_file (f, "", fdopen_mode::truncate);
{
- ifdstream ifs (-1, ifdstream::badbit);
+ ifdstream ifs (ifdstream::badbit);
ifs.open (f);
string s;
@@ -258,7 +259,7 @@ main (int argc, const char* argv[])
}
{
- ifdstream ifs (-1, fdstream_mode::text, ifdstream::badbit);
+ ifdstream ifs (nullfd, fdstream_mode::text, ifdstream::badbit);
ifs.open (f);
string s;
@@ -268,7 +269,7 @@ main (int argc, const char* argv[])
// Check creating unopened ofdstream with a non-default exception mask.
//
{
- ofdstream ofs (-1, ifdstream::badbit);
+ ofdstream ofs (ifdstream::badbit);
ofs.open (f);
istringstream is;
@@ -277,7 +278,7 @@ main (int argc, const char* argv[])
}
{
- ofdstream ofs (-1, fdstream_mode::binary, ifdstream::badbit);
+ ofdstream ofs (nullfd, fdstream_mode::binary, ifdstream::badbit);
ofs.open (f);
istringstream is;
@@ -406,8 +407,8 @@ main (int argc, const char* argv[])
const char* args[] = {argv[0], "-c", nullptr};
process pr (args, -1, -1);
- ofdstream os (pr.out_fd);
- ifdstream is (pr.in_ofd, fdstream_mode::non_blocking);
+ ofdstream os (move (pr.out_fd));
+ ifdstream is (move (pr.in_ofd), fdstream_mode::non_blocking);
const string s (
"0123456789\nABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz");
diff --git a/tests/process/driver.cxx b/tests/process/driver.cxx
index d59b1a7..bc75cc2 100644
--- a/tests/process/driver.cxx
+++ b/tests/process/driver.cxx
@@ -65,15 +65,15 @@ exec (const path& p,
bool s;
r = !pr.try_wait (s); // Couldn't exit as waiting for the input.
- auto bin_mode = [bin](int fd) -> int
- {
- if (bin)
- fdmode (fd, fdstream_mode::binary);
+ auto bin_mode = [bin](auto_fd fd) -> auto_fd
+ {
+ if (bin)
+ fdmode (fd.get (), fdstream_mode::binary);
- return fd;
- };
+ return fd;
+ };
- ofdstream os (bin_mode (pr.out_fd));
+ ofdstream os (bin_mode (move (pr.out_fd)));
copy (in.begin (), in.end (), ostream_iterator<char> (os));
os.close ();
@@ -89,12 +89,11 @@ exec (const path& p,
// overall pipeline looks like 'os -> pr -> pr2 -> pr3 -> is'.
//
process pr3 (cwd, args.data (), -1, -1, -2);
- process pr2 (cwd, args.data (), pr, bin_mode (pr3.out_fd), -2);
- bool cr (fdclose (pr3.out_fd));
- assert (cr);
+ process pr2 (
+ cwd, args.data (), pr, bin_mode (move (pr3.out_fd)).get (), -2);
- ifdstream is (bin_mode (pr3.in_ofd));
+ ifdstream is (bin_mode (move (pr3.in_ofd)));
o = vector<char> (
(istreambuf_iterator<char> (is)), istreambuf_iterator<char> ());
@@ -104,7 +103,7 @@ exec (const path& p,
}
else
{
- ifdstream is (bin_mode (pr.in_ofd));
+ ifdstream is (bin_mode (move (pr.in_ofd)));
o = vector<char> (
(istreambuf_iterator<char> (is)), istreambuf_iterator<char> ());
@@ -125,7 +124,7 @@ exec (const path& p,
if (err && !out)
{
- ifdstream is (bin_mode (pr.in_efd));
+ ifdstream is (bin_mode (move (pr.in_efd)));
vector<char> e
((istreambuf_iterator<char> (is)), istreambuf_iterator<char> ());