From owner-freebsd-hackers@freebsd.org Mon Jan 1 05:03:18 2018 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 771FFEB3C0D for ; Mon, 1 Jan 2018 05:03:18 +0000 (UTC) (envelope-from markmi@dsl-only.net) Received: from asp.reflexion.net (outbound-mail-210-136.reflexion.net [208.70.210.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1BE25752D1 for ; Mon, 1 Jan 2018 05:03:17 +0000 (UTC) (envelope-from markmi@dsl-only.net) Received: (qmail 18493 invoked from network); 1 Jan 2018 05:03:11 -0000 Received: from unknown (HELO mail-cs-01.app.dca.reflexion.local) (10.81.19.1) by 0 (rfx-qmail) with SMTP; 1 Jan 2018 05:03:11 -0000 Received: by mail-cs-01.app.dca.reflexion.local (Reflexion email security v8.40.3) with SMTP; Mon, 01 Jan 2018 00:03:11 -0500 (EST) Received: (qmail 24297 invoked from network); 1 Jan 2018 05:03:11 -0000 Received: from unknown (HELO iron2.pdx.net) (69.64.224.71) by 0 (rfx-qmail) with (AES256-SHA encrypted) SMTP; 1 Jan 2018 05:03:11 -0000 Received: from [192.168.1.25] (c-76-115-7-162.hsd1.or.comcast.net [76.115.7.162]) by iron2.pdx.net (Postfix) with ESMTPSA id 2BAFBEC8B38; Sun, 31 Dec 2017 21:03:10 -0800 (PST) From: Mark Millard Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Mime-Version: 1.0 (Mac OS X Mail 10.3 \(3273\)) Subject: Re: Is it considered to be ok to not check the return code of close(2) in base? Date: Sun, 31 Dec 2017 21:03:09 -0800 References: <201801010305.w0135luG084158@pdx.rh.CN85.dnsmgr.net> <559541DD-3287-4473-B7DE-B4DDC6860DF7@dsl-only.net> To: "Rodney W. Grimes" , phk@phk.freebsd.dk, FreeBSD Hackers In-Reply-To: <559541DD-3287-4473-B7DE-B4DDC6860DF7@dsl-only.net> Message-Id: <5AD2D86A-2515-4D4D-91B2-1919531F7CC3@dsl-only.net> X-Mailer: Apple Mail (2.3273) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Jan 2018 05:03:18 -0000 On 2017-Dec-31, at 7:17 PM, Mark Millard wrote: > On 2017-Dec-31, at 7:05 PM, Rodney W. Grimes = wrote: >=20 >>> Poul-Henning Kamp phk at phk.freebsd.dk wrote on >>> Sat Dec 30 20:35:35 UTC 2017 : >>>=20 >>>> But if you just close a file, and you're 100% sure that will work, >>>> you should write it as: >>>>=20 >>>> assert(close(fd) =3D=3D 0); >>>>=20 >>>> To tell the rest of us about your assumption and your confidence in = it. >>>=20 >>> Quoting the FreeBSD assert man page: >>>=20 >>> QUOTE >>> The assert() macro may be removed at compile time by = defining NDEBUG as a >>> macro (e.g., by using the cc(1) option -DNDEBUG). >>> ENDQUOTE >>>=20 >>> This makes required-actions inside asserts dangerous, >>> at least without guarantees that NDEBUG will be >>> undefined. Trying to guarantee that NDEBUG will be >>> undefined would generally be a bad idea. >>>=20 >>> So, >>>=20 >>> assert(close(fd) =3D=3D 0); >>>=20 >>> is a bad coding practice in my view. >>=20 >> Less bad than either of >> (void)close(fd)); >> close(fd); >=20 > Hmm. If one is not to check the status code, > then just do not close the file, at least for > NDEBUG style compiles. Seems odd to me. >=20 > "assert" indicates optional code, not required > code. (This is despite its name.) >=20 > In my view: Both errors need to be avoided and > my point still stands: the example is not a > reasonable way to code. >=20 > One could invent an alternate to assert under > a related name that does not make code > disappear (not even for NDEBUG). "assert" > is just not the right facility to express > just: >=20 > tell the rest of us about your assumption and your confidence in it >=20 > without also indicating: optional code. Going in another direction for when NDEBUG is undefined: assert(expression_evaluating_to_false) is, in part, defined to call abort(). abort() in turn is defined such that: "functions passed to atexit() are not called" also, "[w]hether open resources such as files are closed is implementation defined". (Quoted from http://en.cppreference.com/w/c/program/abort . I can get the standard's wording if needed.) Open Group Base Specifications Issue 7 states in its description of abort: "The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2008 defers to the ISO C standard". Before Issue 6 the wording apparently required an attempt to fclose all streams --but that made abort necessarily not async-signal-safe. C99 requires the async-signal-safe status. ( http://pubs.opengroup.org/onlinepubs/9699919799/functions/abort.html ) As for C++: "Destructors of variables with automatic, thread local (since C++11) and static storage durations are not called. Functions registered with std::atexit() and std::at_quick_exit (since C++11) are also not called. Whether open resources such as files are closed is implementation defined." ( http://en.cppreference.com/w/cpp/utility/program/abort ) asserts that call abort are difficult to guarantee specific program-exit behavior for, based on just the standards anyway. =3D=3D=3D Mark Millard markmi at dsl-only.net