From 59076540bce2380bade31edba78b8dd421a03d3c Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 24 Feb 2015 11:05:02 +0000 Subject: [PATCH] * 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. --- winsup/cygwin/ChangeLog | 10 ++++++++++ winsup/cygwin/fhandler.cc | 15 ++++++++++++--- winsup/cygwin/fhandler.h | 7 ++++++- winsup/cygwin/release/1.7.35 | 5 +++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 746881500..21a62461e 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,13 @@ +2015-02-24 Corinna Vinschen + + * 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 * include/sys/socket.h (sockatmark): Add prototype. 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 diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 0298a6f6a..10eacd106 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -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); diff --git a/winsup/cygwin/release/1.7.35 b/winsup/cygwin/release/1.7.35 index 564698907..93335bcdb 100644 --- a/winsup/cygwin/release/1.7.35 +++ b/winsup/cygwin/release/1.7.35 @@ -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