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, "r"); for (;;) { int actualread = gzread(gzfile, &buffer[0], sizeof(buffer)); if (actualread < 0) { int err; const char *errmsg = gzerror(gzfile, &err); if (err == Z_ERRNO && errno == EINTR) continue; errx(_("read error: %s"), errmsg); } if (actualread == 0) /* EOF! */ break; write(fd_out, &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->z_err = Z_OK; clearerr(s->file); } What do you think? Jonathan -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org