Cygwin: new class fhandler_pipe_fifo
This is a parent of fhandler_pipe and fhandler_fifo for code that is common between the two classes. Currently it just contains max_atomic_write and raw_write(). The latter is identical to what used to be fhandler_pipe::raw_write().
This commit is contained in:
parent
eb50f82677
commit
085fc12948
|
@ -1168,12 +1168,24 @@ class fhandler_socket_unix : public fhandler_socket
|
||||||
|
|
||||||
#endif /* __WITH_AF_UNIX */
|
#endif /* __WITH_AF_UNIX */
|
||||||
|
|
||||||
class fhandler_pipe: public fhandler_base
|
/* A parent of fhandler_pipe and fhandler_fifo. */
|
||||||
|
class fhandler_pipe_fifo: public fhandler_base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
size_t max_atomic_write;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fhandler_pipe_fifo ();
|
||||||
|
|
||||||
|
ssize_t __reg3 raw_write (const void *ptr, size_t len);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class fhandler_pipe: public fhandler_pipe_fifo
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
HANDLE read_mtx;
|
HANDLE read_mtx;
|
||||||
pid_t popen_pid;
|
pid_t popen_pid;
|
||||||
size_t max_atomic_write;
|
|
||||||
void set_pipe_non_blocking (bool nonblocking);
|
void set_pipe_non_blocking (bool nonblocking);
|
||||||
public:
|
public:
|
||||||
fhandler_pipe ();
|
fhandler_pipe ();
|
||||||
|
@ -1193,7 +1205,6 @@ public:
|
||||||
int dup (fhandler_base *child, int);
|
int dup (fhandler_base *child, int);
|
||||||
int close ();
|
int close ();
|
||||||
void __reg3 raw_read (void *ptr, size_t& len);
|
void __reg3 raw_read (void *ptr, size_t& len);
|
||||||
ssize_t __reg3 raw_write (const void *ptr, size_t len);
|
|
||||||
int ioctl (unsigned int cmd, void *);
|
int ioctl (unsigned int cmd, void *);
|
||||||
int fcntl (int cmd, intptr_t);
|
int fcntl (int cmd, intptr_t);
|
||||||
int __reg2 fstat (struct stat *buf);
|
int __reg2 fstat (struct stat *buf);
|
||||||
|
@ -1319,7 +1330,7 @@ public:
|
||||||
{ InterlockedExchange (&_sh_fc_handler_updated, val); }
|
{ InterlockedExchange (&_sh_fc_handler_updated, val); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class fhandler_fifo: public fhandler_base
|
class fhandler_fifo: public fhandler_pipe_fifo
|
||||||
{
|
{
|
||||||
/* Handles to named events shared by all fhandlers for a given FIFO. */
|
/* Handles to named events shared by all fhandlers for a given FIFO. */
|
||||||
HANDLE read_ready; /* A reader is open; OK for a writer to open. */
|
HANDLE read_ready; /* A reader is open; OK for a writer to open. */
|
||||||
|
@ -1342,7 +1353,6 @@ class fhandler_fifo: public fhandler_base
|
||||||
int nhandlers; /* Number of elements in the array. */
|
int nhandlers; /* Number of elements in the array. */
|
||||||
af_unix_spinlock_t _fifo_client_lock;
|
af_unix_spinlock_t _fifo_client_lock;
|
||||||
bool reader, writer, duplexer;
|
bool reader, writer, duplexer;
|
||||||
size_t max_atomic_write;
|
|
||||||
fifo_reader_id_t me;
|
fifo_reader_id_t me;
|
||||||
|
|
||||||
HANDLE shmem_handle;
|
HANDLE shmem_handle;
|
||||||
|
@ -1447,7 +1457,6 @@ public:
|
||||||
bool isfifo () const { return true; }
|
bool isfifo () const { return true; }
|
||||||
void set_close_on_exec (bool val);
|
void set_close_on_exec (bool val);
|
||||||
void __reg3 raw_read (void *ptr, size_t& ulen);
|
void __reg3 raw_read (void *ptr, size_t& ulen);
|
||||||
ssize_t __reg3 raw_write (const void *ptr, size_t ulen);
|
|
||||||
void fixup_after_fork (HANDLE);
|
void fixup_after_fork (HANDLE);
|
||||||
void fixup_after_exec ();
|
void fixup_after_exec ();
|
||||||
int __reg2 fstat (struct stat *buf);
|
int __reg2 fstat (struct stat *buf);
|
||||||
|
|
|
@ -128,13 +128,12 @@ STATUS_PIPE_EMPTY simply means there's no data to be read. */
|
||||||
static NO_COPY fifo_reader_id_t null_fr_id = { .winpid = 0, .fh = NULL };
|
static NO_COPY fifo_reader_id_t null_fr_id = { .winpid = 0, .fh = NULL };
|
||||||
|
|
||||||
fhandler_fifo::fhandler_fifo ():
|
fhandler_fifo::fhandler_fifo ():
|
||||||
fhandler_base (),
|
fhandler_pipe_fifo (),
|
||||||
read_ready (NULL), write_ready (NULL), writer_opening (NULL),
|
read_ready (NULL), write_ready (NULL), writer_opening (NULL),
|
||||||
owner_needed_evt (NULL), owner_found_evt (NULL), update_needed_evt (NULL),
|
owner_needed_evt (NULL), owner_found_evt (NULL), update_needed_evt (NULL),
|
||||||
cancel_evt (NULL), thr_sync_evt (NULL), pipe_name_buf (NULL),
|
cancel_evt (NULL), thr_sync_evt (NULL), pipe_name_buf (NULL),
|
||||||
fc_handler (NULL), shandlers (0), nhandlers (0),
|
fc_handler (NULL), shandlers (0), nhandlers (0),
|
||||||
reader (false), writer (false), duplexer (false),
|
reader (false), writer (false), duplexer (false),
|
||||||
max_atomic_write (DEFAULT_PIPEBUFSIZE),
|
|
||||||
me (null_fr_id), shmem_handle (NULL), shmem (NULL),
|
me (null_fr_id), shmem_handle (NULL), shmem (NULL),
|
||||||
shared_fc_hdl (NULL), shared_fc_handler (NULL)
|
shared_fc_hdl (NULL), shared_fc_handler (NULL)
|
||||||
{
|
{
|
||||||
|
@ -1138,99 +1137,6 @@ fhandler_fifo::wait (HANDLE h)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t __reg3
|
|
||||||
fhandler_fifo::raw_write (const void *ptr, size_t len)
|
|
||||||
{
|
|
||||||
ssize_t ret = -1;
|
|
||||||
size_t nbytes = 0;
|
|
||||||
ULONG chunk;
|
|
||||||
NTSTATUS status = STATUS_SUCCESS;
|
|
||||||
IO_STATUS_BLOCK io;
|
|
||||||
HANDLE evt = NULL;
|
|
||||||
|
|
||||||
if (!len)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (len <= max_atomic_write)
|
|
||||||
chunk = len;
|
|
||||||
else if (is_nonblocking ())
|
|
||||||
chunk = len = max_atomic_write;
|
|
||||||
else
|
|
||||||
chunk = max_atomic_write;
|
|
||||||
|
|
||||||
/* Create a wait event if the FIFO is in blocking mode. */
|
|
||||||
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
|
|
||||||
{
|
|
||||||
__seterrno ();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write in chunks, accumulating a total. If there's an error, just
|
|
||||||
return the accumulated total unless the first write fails, in
|
|
||||||
which case return -1. */
|
|
||||||
while (nbytes < len)
|
|
||||||
{
|
|
||||||
ULONG_PTR nbytes_now = 0;
|
|
||||||
size_t left = len - nbytes;
|
|
||||||
ULONG len1;
|
|
||||||
DWORD waitret = WAIT_OBJECT_0;
|
|
||||||
|
|
||||||
if (left > chunk)
|
|
||||||
len1 = chunk;
|
|
||||||
else
|
|
||||||
len1 = (ULONG) left;
|
|
||||||
nbytes_now = 0;
|
|
||||||
status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
|
|
||||||
(PVOID) ptr, len1, NULL, NULL);
|
|
||||||
if (evt && status == STATUS_PENDING)
|
|
||||||
{
|
|
||||||
waitret = cygwait (evt);
|
|
||||||
if (waitret == WAIT_OBJECT_0)
|
|
||||||
status = io.Status;
|
|
||||||
}
|
|
||||||
if (waitret == WAIT_CANCELED)
|
|
||||||
status = STATUS_THREAD_CANCELED;
|
|
||||||
else if (waitret == WAIT_SIGNALED)
|
|
||||||
status = STATUS_THREAD_SIGNALED;
|
|
||||||
else if (isclosed ()) /* A signal handler might have closed the fd. */
|
|
||||||
{
|
|
||||||
if (waitret == WAIT_OBJECT_0)
|
|
||||||
set_errno (EBADF);
|
|
||||||
else
|
|
||||||
__seterrno ();
|
|
||||||
}
|
|
||||||
else if (NT_SUCCESS (status))
|
|
||||||
{
|
|
||||||
nbytes_now = io.Information;
|
|
||||||
/* NtWriteFile returns success with # of bytes written == 0
|
|
||||||
if writing on a non-blocking pipe fails because the pipe
|
|
||||||
buffer doesn't have sufficient space. */
|
|
||||||
if (nbytes_now == 0)
|
|
||||||
set_errno (EAGAIN);
|
|
||||||
ptr = ((char *) ptr) + chunk;
|
|
||||||
nbytes += nbytes_now;
|
|
||||||
}
|
|
||||||
else if (STATUS_PIPE_IS_CLOSED (status))
|
|
||||||
{
|
|
||||||
set_errno (EPIPE);
|
|
||||||
raise (SIGPIPE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__seterrno_from_nt_status (status);
|
|
||||||
if (nbytes_now == 0)
|
|
||||||
len = 0; /* Terminate loop. */
|
|
||||||
if (nbytes > 0)
|
|
||||||
ret = nbytes;
|
|
||||||
}
|
|
||||||
if (evt)
|
|
||||||
NtClose (evt);
|
|
||||||
if (status == STATUS_THREAD_SIGNALED && ret < 0)
|
|
||||||
set_errno (EINTR);
|
|
||||||
else if (status == STATUS_THREAD_CANCELED)
|
|
||||||
pthread::static_cancel_self ();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Called from raw_read and select.cc:peek_fifo. */
|
/* Called from raw_read and select.cc:peek_fifo. */
|
||||||
int
|
int
|
||||||
fhandler_fifo::take_ownership (DWORD timeout)
|
fhandler_fifo::take_ownership (DWORD timeout)
|
||||||
|
|
|
@ -28,10 +28,15 @@ STATUS_PIPE_EMPTY simply means there's no data to be read. */
|
||||||
|| _s == STATUS_PIPE_BROKEN \
|
|| _s == STATUS_PIPE_BROKEN \
|
||||||
|| _s == STATUS_PIPE_EMPTY; })
|
|| _s == STATUS_PIPE_EMPTY; })
|
||||||
|
|
||||||
fhandler_pipe::fhandler_pipe ()
|
fhandler_pipe_fifo::fhandler_pipe_fifo ()
|
||||||
: fhandler_base (), popen_pid (0)
|
: fhandler_base (), max_atomic_write (DEFAULT_PIPEBUFSIZE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fhandler_pipe::fhandler_pipe ()
|
||||||
|
: fhandler_pipe_fifo (), popen_pid (0)
|
||||||
{
|
{
|
||||||
max_atomic_write = DEFAULT_PIPEBUFSIZE;
|
|
||||||
need_fork_fixup (true);
|
need_fork_fixup (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +345,7 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t __reg3
|
ssize_t __reg3
|
||||||
fhandler_pipe::raw_write (const void *ptr, size_t len)
|
fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
|
||||||
{
|
{
|
||||||
size_t nbytes = 0;
|
size_t nbytes = 0;
|
||||||
ULONG chunk;
|
ULONG chunk;
|
||||||
|
@ -358,7 +363,7 @@ fhandler_pipe::raw_write (const void *ptr, size_t len)
|
||||||
else
|
else
|
||||||
chunk = max_atomic_write;
|
chunk = max_atomic_write;
|
||||||
|
|
||||||
/* Create a wait event if the pipe is in blocking mode. */
|
/* Create a wait event if the pipe or fifo is in blocking mode. */
|
||||||
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
|
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
|
|
Loading…
Reference in New Issue