Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler.cc')
-rw-r--r--winsup/cygwin/fhandler.cc120
1 files changed, 77 insertions, 43 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 0e0981fdc..714c46ad0 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1037,10 +1037,17 @@ fhandler_base::close ()
__seterrno ();
}
- destroy_overlapped ();
return res;
}
+
+int
+fhandler_base_overlapped::close ()
+{
+ destroy_overlapped ();
+ return fhandler_base::close ();
+}
+
int
fhandler_base::ioctl (unsigned int cmd, void *buf)
{
@@ -1162,11 +1169,17 @@ fhandler_base::dup (fhandler_base *child)
VerifyHandle (nh);
child->set_io_handle (nh);
}
- if (get_overlapped ())
- child->setup_overlapped ();
return 0;
}
+int
+fhandler_base_overlapped::dup (fhandler_base *child)
+{
+ int res = fhandler_base::dup (child) ||
+ ((fhandler_base_overlapped *) child)->setup_overlapped ();
+ return res;
+}
+
int fhandler_base::fcntl (int cmd, void *arg)
{
int res;
@@ -1335,8 +1348,6 @@ fhandler_base::fork_fixup (HANDLE parent, HANDLE &h, const char *name)
VerifyHandle (h);
res = true;
}
- if (get_overlapped ())
- setup_overlapped ();
return res;
}
@@ -1355,22 +1366,31 @@ fhandler_base::fixup_after_fork (HANDLE parent)
debug_printf ("inheriting '%s' from parent", get_name ());
if (!nohandle ())
fork_fixup (parent, io_handle, "io_handle");
- if (get_overlapped ())
- setup_overlapped ();
/* POSIX locks are not inherited across fork. */
if (unique_id)
del_my_locks (after_fork);
}
void
+fhandler_base_overlapped::fixup_after_fork (HANDLE parent)
+{
+ setup_overlapped ();
+ fhandler_base::fixup_after_fork (parent);
+}
+
+void
fhandler_base::fixup_after_exec ()
{
debug_printf ("here for '%s'", get_name ());
- if (get_overlapped ())
- setup_overlapped ();
if (unique_id && close_on_exec ())
del_my_locks (after_exec);
}
+void
+fhandler_base_overlapped::fixup_after_exec ()
+{
+ setup_overlapped ();
+ fhandler_base::fixup_after_exec ();
+}
bool
fhandler_base::is_nonblocking ()
@@ -1644,27 +1664,18 @@ fhandler_base::fpathconf (int v)
/* Overlapped I/O */
-bool
-fhandler_base::setup_overlapped (bool doit)
+int
+fhandler_base_overlapped::setup_overlapped ()
{
OVERLAPPED *ov = get_overlapped_buffer ();
memset (ov, 0, sizeof (*ov));
- bool res;
- if (doit)
- {
- set_overlapped (ov);
- res = !!(ov->hEvent = CreateEvent (&sec_none_nih, true, true, NULL));
- }
- else
- {
- set_overlapped (NULL);
- res = false;
- }
- return res;
+ set_overlapped (ov);
+ ov->hEvent = CreateEvent (&sec_none_nih, true, true, NULL);
+ return ov->hEvent ? 0 : -1;
}
void
-fhandler_base::destroy_overlapped ()
+fhandler_base_overlapped::destroy_overlapped ()
{
OVERLAPPED *ov = get_overlapped ();
if (ov && ov->hEvent)
@@ -1672,10 +1683,26 @@ fhandler_base::destroy_overlapped ()
CloseHandle (ov->hEvent);
ov->hEvent = NULL;
}
+ io_pending = false;
+ get_overlapped () = NULL;
+}
+
+bool
+fhandler_base_overlapped::has_ongoing_io ()
+{
+ if (!io_pending)
+ return false;
+ if (WaitForSingleObject (get_overlapped ()->hEvent, 0) != WAIT_OBJECT_0)
+ {
+ set_errno (EAGAIN);
+ return true;
+ }
+ io_pending = false;
+ return false;
}
int
-fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
+fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD len)
{
if (!get_overlapped ())
return inres;
@@ -1687,6 +1714,7 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le
{
if (inres || err == ERROR_IO_PENDING)
{
+ io_pending = err == ERROR_IO_PENDING;
if (writing && !inres)
*bytes = len; /* This really isn't true but it seems like
this is a corner-case for linux's
@@ -1758,32 +1786,38 @@ fhandler_base::wait_overlapped (bool inres, bool writing, DWORD *bytes, DWORD le
}
void __stdcall
-fhandler_base::read_overlapped (void *ptr, size_t& len)
+fhandler_base_overlapped::read_overlapped (void *ptr, size_t& len)
{
DWORD nbytes;
- while (1)
- {
- bool res = ReadFile (get_handle (), ptr, len, &nbytes,
- get_overlapped ());
- int wres = wait_overlapped (res, false, &nbytes);
- if (wres || !_my_tls.call_signal_handler ())
- break;
- }
+ if (has_ongoing_io ())
+ nbytes = (DWORD) -1;
+ else
+ while (1)
+ {
+ bool res = ReadFile (get_handle (), ptr, len, &nbytes,
+ get_overlapped ());
+ int wres = wait_overlapped (res, false, &nbytes);
+ if (wres || !_my_tls.call_signal_handler ())
+ break;
+ }
len = (size_t) nbytes;
}
ssize_t __stdcall
-fhandler_base::write_overlapped (const void *ptr, size_t len)
+fhandler_base_overlapped::write_overlapped (const void *ptr, size_t len)
{
DWORD nbytes;
- while (1)
- {
- bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
- get_overlapped ());
- int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
- if (wres || !_my_tls.call_signal_handler ())
- break;
- }
+ if (has_ongoing_io ())
+ nbytes = (DWORD) -1;
+ else
+ while (1)
+ {
+ bool res = WriteFile (get_output_handle (), ptr, len, &nbytes,
+ get_overlapped ());
+ int wres = wait_overlapped (res, true, &nbytes, (size_t) len);
+ if (wres || !_my_tls.call_signal_handler ())
+ break;
+ }
debug_printf ("returning %u", nbytes);
return nbytes;
}