summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-02-24 11:05:02 +0000
committerCorinna Vinschen <corinna@vinschen.de>2015-02-24 11:05:02 +0000
commit59076540bce2380bade31edba78b8dd421a03d3c (patch)
tree5a545da9009afa80211d20b3bd45e9728f9abc9e /winsup/cygwin/fhandler.cc
parentf8a6c963061eb9dcaa0bc0582e0e31cdfcec0d3c (diff)
downloadcygnal-59076540bce2380bade31edba78b8dd421a03d3c.tar.gz
cygnal-59076540bce2380bade31edba78b8dd421a03d3c.tar.bz2
cygnal-59076540bce2380bade31edba78b8dd421a03d3c.zip
* fhandler.h (class fhandler_base): Add was_nonblocking status flag.
* fhandler.cc (fhandler_base::set_flags): Set was_nonblocking if the O_NONBLOCK flag has been specified. (fhandler_base_overlapped::close): Check for was_nonblocking instead of for is_nonblocking. Explain why. (fhandler_base::set_nonblocking): Set was_nonblocking if noblocking mode gets enabled.
Diffstat (limited to 'winsup/cygwin/fhandler.cc')
-rw-r--r--winsup/cygwin/fhandler.cc15
1 files changed, 12 insertions, 3 deletions
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 8444d4abc..6f024da32 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1,7 +1,7 @@
/* fhandler.cc. See console.cc for fhandler_console functions.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011, 2012, 2013 Red Hat, Inc.
+ 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Red Hat, Inc.
This file is part of Cygwin.
@@ -205,6 +205,8 @@ fhandler_base::set_flags (int flags, int supplied_bin)
bin = wbinary () || rbinary () ? O_BINARY : O_TEXT;
openflags = flags | bin;
+ if (openflags & O_NONBLOCK)
+ was_nonblocking (true);
bin &= O_BINARY;
rbinary (bin ? true : false);
@@ -1242,8 +1244,13 @@ fhandler_base_overlapped::close ()
int res;
int writer = (get_access () & GENERIC_WRITE);
/* Need to treat non-blocking I/O specially because Windows appears to
- be brain-dead */
- if (writer && is_nonblocking () && has_ongoing_io ())
+ be brain-dead. We're checking here if the descriptor was ever set
+ to nonblocking, rather than checking if it's nonblocking at close time.
+ The reason is that applications may switch back to blocking (for the
+ sake of some other application accessing this descriptor) without
+ performaing any further I/O. These applications would suffer data
+ loss, which this workaround is trying to fix. */
+ if (writer && was_nonblocking () && has_ongoing_io ())
{
clone (HEAP_3_FHANDLER)->check_later ();
res = 0;
@@ -1629,6 +1636,8 @@ fhandler_base::set_nonblocking (int yes)
int current = openflags & O_NONBLOCK_MASK;
int new_flags = yes ? (!current ? O_NONBLOCK : current) : 0;
openflags = (openflags & ~O_NONBLOCK_MASK) | new_flags;
+ if (new_flags)
+ was_nonblocking (true);
}
int