[From nobody Thu Sep 12 14:37:22 2019
Return-path: &lt;debbugs@rietz.debian.org&gt;
Envelope-to: broonie@sirena.org.uk
Delivery-date: Tue, 02 Feb 2010 19:18:12 +0000
Received: from rietz.debian.org ([140.211.166.43])
 by cassiel.sirena.org.uk with esmtp (Exim 4.69)
 (envelope-from &lt;debbugs@rietz.debian.org&gt;) id 1NcOGJ-000802-EA
 for broonie@sirena.org.uk; Tue, 02 Feb 2010 19:18:12 +0000
Received: from debbugs by rietz.debian.org with local (Exim 4.63)
 (envelope-from &lt;debbugs@rietz.debian.org&gt;)
 id 1NcOAP-0004eJ-6H; Tue, 02 Feb 2010 19:12:05 +0000
X-Loop: owner@bugs.debian.org
Reply-To: Jonathan Nieder &lt;jrnieder@gmail.com&gt;, 568149@bugs.debian.org
Resent-From: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
Resent-To: debian-bugs-dist@lists.debian.org
Resent-CC: Mark Brown &lt;broonie@debian.org&gt;
X-Loop: owner@bugs.debian.org
Resent-Date: Tue, 02 Feb 2010 19:12:01 +0000
Resent-Message-ID: &lt;handler.568149.B.126513747912663@bugs.debian.org&gt;
X-Debian-PR-Message: report 568149
X-Debian-PR-Package: zlib1g-dev
X-Debian-PR-Keywords: 
X-Debian-PR-Source: zlib
Received: via spool by submit@bugs.debian.org id=B.126513747912663
 (code B ref -1); Tue, 02 Feb 2010 19:12:01 +0000
Received: (at submit) by bugs.debian.org; 2 Feb 2010 19:04:39 +0000
Received: from mail-iw0-f199.google.com ([209.85.223.199])
 by rietz.debian.org with esmtp (Exim 4.63)
 (envelope-from &lt;jrnieder@gmail.com&gt;) id 1NcO3D-0003HU-9A
 for submit@bugs.debian.org; Tue, 02 Feb 2010 19:04:39 +0000
Received: by iwn37 with SMTP id 37so613044iwn.24
 for &lt;submit@bugs.debian.org&gt;; Tue, 02 Feb 2010 11:04:33 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
 h=domainkey-signature:received:received:date:from:to:subject
 :message-id:mime-version:content-type:content-disposition
 :content-transfer-encoding:user-agent;
 bh=CNxEMYylMFXCTyple0qqtHsizzbs0nfLBNOf7ozoWDk=;
 b=Dl6C2utanl3rGw2GuVkO0wg+IM2pHGnm2S2nLq6Yaez5kHCRjrB2vhVt3JdQHHK2qM
 HElaVpFq+PbHBz6BJSgDEx5Ouj8iBAowUpF7qnmJCUbbbnho44XHPH/V1wgpByEN3E5v
 Qcr4+6HOcvxZstuhEyfnbHzUJWhiKVrMZDaRc=
DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma;
 h=date:from:to:subject:message-id:mime-version:content-type
 :content-disposition:content-transfer-encoding:user-agent;
 b=BPLBeniaIzkPy3n3CbYw83LonCXKARTt3e5BG87fqDDLc+Ld4gTCoFNNFt5Qbui/9+
 aqi4XHjFMmJfFtRjo1t7YP4y72oBdGEUMmLNbn/frpPmR9JT0u9d3vUwWWjRzkIB1Eih
 ZjDFwjmnXbjew0ef3Ei24RKywjubJXqqvvewU=
Received: by 10.231.147.148 with SMTP id l20mr849178ibv.77.1265137473703;
 Tue, 02 Feb 2010 11:04:33 -0800 (PST)
Received: from progeny.tock (c-98-212-3-231.hsd1.il.comcast.net [98.212.3.231])
 by mx.google.com with ESMTPS id 23sm6742244iwn.11.2010.02.02.11.04.33
 (version=SSLv3 cipher=RC4-MD5); Tue, 02 Feb 2010 11:04:33 -0800 (PST)
Date: Tue, 2 Feb 2010 13:04:29 -0600
From: Jonathan Nieder &lt;jrnieder@gmail.com&gt;
To: submit@bugs.debian.org
Message-ID: &lt;20100202190429.GA11872@progeny.tock&gt;
 (sfid-20100202_191812_815320_F4EFA19D)
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
User-Agent: Mutt/1.5.20 (2009-06-14)
Delivered-To: submit@bugs.debian.org
Resent-Sender: Debian BTS &lt;debbugs@rietz.debian.org&gt;
Resent-Date: Tue, 02 Feb 2010 19:12:05 +0000
X-SA-Exim-Connect-IP: 140.211.166.43
X-SA-Exim-Mail-From: debbugs@rietz.debian.org
X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on
 cassiel.sirena.org.uk
X-Spam-Level: 
X-Spam-Status: No, score=-3.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW
 autolearn=ham version=3.2.5
Subject: Bug#568149: zlib: please allow resuming after EINTR
X-SA-Exim-Version: 4.2.1 (built Wed, 25 Jun 2008 17:14:11 +0000)
X-SA-Exim-Scanned: Yes (on cassiel.sirena.org.uk)
X-CRM114-Version: 20080326-BlameSentansoken ( TRE 0.7.5 (LGPL) ) MR-99794A9B 
X-CRM114-CacheID: sfid-20100202_191812_815320_F4EFA19D 
X-CRM114-Status: GOOD (  20.55  )

Package: zlib1g-dev
Version: 1:1.2.3.4.dfsg-3
Severity: wishlist

Hi,

zlib’s gzFile interface provides no way I can see to recover from
EINTR.

Context:

When library code makes syscalls, I live in constant danger that the
application may have installed a signal handler with SA_RESTART
disabled.  If the system call is interrupted by a signal, depending
on the application, one of three behaviors would be appropriate:

 a. if the goal is to walk the stack after a SIGINT and clean up
    before exiting, my function should return quickly to the
    application with an error;

 b. if the interruption is just a side effect of something else (maybe
    this is a System V-based system and the application writer forgot
    to use SA_RESTART, or maybe the interruption was intended for some
    other thread), my function should restart the call and return with
    success once the operation succeeds.

 c. if the interruption (perhaps from SIGIO) represents some
    high-priority job that needs to be done soon, my function should
    let that job finish and then resume.

The usual way to handle this is to either pick one or leave it to the
application by returning with enough information to resume the
operation later.

In my case, the library was libdpkg, and the chosen behavior was
option b.  Simple, right?

	char buffer[BUFSZ];
	int actualread;
	gzFile gzfile = gzdopen(fd_in, &quot;r&quot;);

	for (;;) {
		int actualread = gzread(gzfile, &amp;buffer[0], sizeof(buffer));

		if (actualread &lt; 0) {
			int err;
			const char *errmsg = gzerror(gzfile, &amp;err);

			if (err == Z_ERRNO &amp;&amp; errno == EINTR)
				continue;
			errx(_(&quot;read error: %s&quot;), errmsg);
		}
		if (actualread == 0) /* EOF! */
			break;
		write(fd_out, &amp;buffer[0], actualread);
	}
	int err = gzclose(gzfile);
	// handle error or return

Unfortunately, when zlib hits its first EINTR, two bad things happen:

 - the error indicator for the underlying stdio stream is set;
 - the error number for the gzFile is set

and there is no way to undo either.  So in fact this is an infinite
loop.

Thoughts about fix:

I would love it if zlib just cleared the error indicator before each
potentially resumable operation (gzread(), gzwrite(), gzseek()).  But
probably someone out there is relying on zlib _not_ to do that, as
part of his implementation of error recovery plan a above, so such a
change would be dangerous.

Better would be to add a new gzclearerr() function to allow the two
error indicators to be explicitly cleared.

	void Z_EXPORT gzclearerr (file)
	    gzFile file;
	{
		gz_stream *s = (gz_stream*)file;

		if (s == NULL) return;

		s-&gt;z_err = Z_OK;
		clearerr(s-&gt;file);
	}

What do you think?

Jonathan



]