* 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.
This commit is contained in:
Corinna Vinschen 2015-02-24 11:05:02 +00:00
parent f8a6c96306
commit 59076540bc
4 changed files with 33 additions and 4 deletions

View File

@ -1,3 +1,13 @@
2015-02-24 Corinna Vinschen <corinna@vinschen.de>
* 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.
2015-02-24 Ken Brown <kbrown@cornell.edu>
* include/sys/socket.h (sockatmark): Add prototype.

View File

@ -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

View File

@ -149,12 +149,16 @@ class fhandler_base
unsigned need_fork_fixup : 1; /* Set if need to fixup after fork. */
unsigned isclosed : 1; /* Set when fhandler is closed. */
unsigned mandatory_locking : 1; /* Windows mandatory locking */
unsigned was_nonblocking : 1; /* Set when setting O_NONBLOCK. Never
reset. This is for the sake of
fhandler_base_overlapped::close. */
public:
status_flags () :
rbinary (0), rbinset (0), wbinary (0), wbinset (0), nohandle (0),
did_lseek (0), query_open (no_query), close_on_exec (0),
need_fork_fixup (0), isclosed (0), mandatory_locking (0)
need_fork_fixup (0), isclosed (0), mandatory_locking (0),
was_nonblocking (0)
{}
} status, open_status;
@ -250,6 +254,7 @@ class fhandler_base
IMPLEMENT_STATUS_FLAG (bool, need_fork_fixup)
IMPLEMENT_STATUS_FLAG (bool, isclosed)
IMPLEMENT_STATUS_FLAG (bool, mandatory_locking)
IMPLEMENT_STATUS_FLAG (bool, was_nonblocking)
int get_default_fmode (int flags);

View File

@ -7,6 +7,8 @@ What's new:
What changed:
-------------
- Performance improvements of the new account DB handling.
Bug Fixes
---------
@ -38,3 +40,6 @@ Bug Fixes
- 64 bit: Avoid misbehaviour in signal mask computation.
Addresses: https://cygwin.com/ml/cygwin/2015-02/msg00665.html
- Avoid data loss on non-blocking pipes after switching back to blocking.
Addresses: https://cygwin.com/ml/cygwin/2015-02/msg00575.html