After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 682819 - EINTR-harden all the things
EINTR-harden all the things
Status: RESOLVED DUPLICATE of bug 656492
Product: glib
Classification: Platform
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
: 564138 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2012-08-27 18:46 UTC by Colin Walters
Modified: 2013-03-18 03:55 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gstdio: Harden g_open() against EINTR (936 bytes, patch)
2012-08-27 18:46 UTC, Colin Walters
committed Details | Review
Handle EINTR for a few more write() calls (1.38 KB, patch)
2012-08-29 15:50 UTC, Colin Walters
committed Details | Review
0001-GUnixOutputStream-Handle-EINTR-for-close.patch (867 bytes, patch)
2013-01-25 15:46 UTC, Colin Walters
rejected Details | Review
0001-Add-g_unix_close_fd-use-it.patch (13.79 KB, patch)
2013-01-25 17:23 UTC, Colin Walters
none Details | Review
0001-Add-g_close-use-it.patch (15.83 KB, patch)
2013-01-25 19:54 UTC, Colin Walters
needs-work Details | Review
0001-Add-g_close-use-it.patch (15.93 KB, patch)
2013-01-29 14:46 UTC, Colin Walters
committed Details | Review

Description Colin Walters 2012-08-27 18:46:29 UTC
Noticed by code inspection, when auditing some of my code for EINTR
handling.
Comment 1 Colin Walters 2012-08-27 18:46:30 UTC
Created attachment 222573 [details] [review]
gstdio: Harden g_open() against EINTR
Comment 2 Dan Winship 2012-08-27 21:29:56 UTC
Comment on attachment 222573 [details] [review]
gstdio: Harden g_open() against EINTR

oh EINTR...
Comment 3 Colin Walters 2012-08-27 22:12:24 UTC
Attachment 222573 [details] pushed as ce976bc - gstdio: Harden g_open() against EINTR
Comment 4 Alexander Larsson 2012-08-29 07:53:58 UTC
What about all the close calls?
Comment 5 Colin Walters 2012-08-29 15:50:53 UTC
Created attachment 222799 [details] [review]
Handle EINTR for a few more write() calls
Comment 6 Colin Walters 2012-08-29 15:51:40 UTC
(In reply to comment #4)
> What about all the close calls?

So there's a *lot* of them...  I could add say g_unix_close_noeintr()?
Comment 7 Colin Walters 2012-08-29 15:55:45 UTC
To be clear, the reason this matters is that someone was complaining about some GNOME-related software crashing after a resume.  The error message had "Interrupted system call" in it.

I think it's something like while suspending, the kernel will offline CPUs and freeze processes, and this may end up generating an EINTR visible to userspace where one normally wouldn't.

Kind of evil to have bugs that only appear when suspending, so we should be defensive.  It doesn't hurt to fix other Unix implementations too.
Comment 8 Dan Winship 2012-08-29 16:21:13 UTC
(In reply to comment #6)
> (In reply to comment #4)
> > What about all the close calls?
> 
> So there's a *lot* of them...  I could add say g_unix_close_noeintr()?

how would that help, as opposed to g_close()? it seems like we would want to check everywhere, since otherwise you're leaking a fd, right?

oh, meanwhile, I just noticed that by default on unix:

#define g_open    open
Comment 9 Alexander Larsson 2012-08-30 07:34:24 UTC
close is not wrapped with g_ like open is, because we generally only have wrappers because we need to do special things on win32 with all the syscalls that take pathnames, and close doesn't.

In general its not really possible to wrap all of these safely, as e.g. the exact definition of "struct stat" and "stat" and other things may wary depending on some defines.

Also, it seems like EINTR should not be handled on close on Linux (although it needs to be on HPUX, dafuq!?):

https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain

http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR
Comment 10 Dan Winship 2012-08-30 12:10:12 UTC
(In reply to comment #9)
> close is not wrapped with g_ like open is, because we generally only have
> wrappers because we need to do special things on win32 with all the syscalls
> that take pathnames, and close doesn't.

Historically, yes, but as of Colin's earlier commit on this bug, g_open() now also does EINTR-retrying on unix. (Except that it doesn't actually get used because of #defines in the header.) 

I think we could usefully use EINTR-retrying read() and write() too...

> In general its not really possible to wrap all of these safely, as e.g. the
> exact definition of "struct stat" and "stat" and other things may wary
> depending on some defines.

Is that still true in modern times? But anyway, we could use a macro. (And the stat man page doesn't list EINTR as a possibility anyway, though maybe that's a bug.)
Comment 11 Alexander Larsson 2012-08-30 14:21:24 UTC
It seems like stat may actually return EINTR, at least on solaris.

http://www.linuxmisc.com/3-solaris/2716b3b80cbf8053.htm
http://lists.gnu.org/archive/html/bug-make/2002-11/msg00022.html

And yeah, off_t and struct stat size is still dependent on LFS defines.

Might make sense to wrap read/write too to avoid this, although these calls are not all that common in glib.
Comment 12 Colin Walters 2013-01-25 15:46:49 UTC
Created attachment 234420 [details] [review]
0001-GUnixOutputStream-Handle-EINTR-for-close.patch
Comment 13 Dan Winship 2013-01-25 15:51:35 UTC
Comment on attachment 234420 [details] [review]
0001-GUnixOutputStream-Handle-EINTR-for-close.patch

According to the link in comment 9, this is explicitly wrong, at least on Linux.
Comment 14 Dan Winship 2013-01-25 15:52:59 UTC
Comment on attachment 222799 [details] [review]
Handle EINTR for a few more write() calls

assuming this still applies, it looks good, although didn't we add a helper function for this at some point?
Comment 15 Colin Walters 2013-01-25 16:02:23 UTC
(In reply to comment #13)
> (From update of attachment 234420 [details] [review])
> According to the link in comment 9, this is explicitly wrong, at least on
> Linux.

Holy shit.  I missed that in this bug.  That's *awful*.  Truly, staggeringly, amazingly awful.  Arrrrgh.
Comment 16 Dan Winship 2013-01-25 16:10:04 UTC
Yes. Yes it is.
Comment 17 Colin Walters 2013-01-25 16:28:44 UTC
Comment on attachment 222799 [details] [review]
Handle EINTR for a few more write() calls

Hm, no I don't see a helper anywhere.  It's probably worth adding one though.
Comment 18 Colin Walters 2013-01-25 17:23:58 UTC
Created attachment 234428 [details] [review]
0001-Add-g_unix_close_fd-use-it.patch
Comment 19 Allison Karlitskaya (desrt) 2013-01-25 17:53:21 UTC
Review of attachment 234428 [details] [review]:

Maybe we could just call it g_close()?
Comment 20 Dan Winship 2013-01-25 17:57:11 UTC
some of those places (eg, glocalfileinputstream) are not unix-specific
Comment 21 Colin Walters 2013-01-25 19:54:06 UTC
Created attachment 234440 [details] [review]
0001-Add-g_close-use-it.patch
Comment 22 Alexander Larsson 2013-01-29 09:48:40 UTC
Review of attachment 234440 [details] [review]:

::: glib/gstdio.c
@@ +874,3 @@
+    }
+  return TRUE;
+}

This seem to override errno in case of an error. I mean, its saved and reused in the g_file_error_from_errno call, but after return of g_close you can't rely on errno. And it seems to me that a bunch of the other code relies on errno being right, like in gio/glocalfileinputstream.c
Comment 23 Colin Walters 2013-01-29 14:46:23 UTC
Created attachment 234732 [details] [review]
0001-Add-g_close-use-it.patch

Correctly re-set errno, update documentation to reflect this.
Comment 24 Alexander Larsson 2013-01-29 15:26:09 UTC
Review of attachment 234732 [details] [review]:

looks good
Comment 25 Colin Walters 2013-01-29 15:33:14 UTC
Leaving this bug open, there's still some incorrect write() calls, though mostly in the tests.
Comment 26 Matthias Clasen 2013-02-03 06:08:40 UTC
*** Bug 564138 has been marked as a duplicate of this bug. ***
Comment 27 Matthias Clasen 2013-03-18 03:55:24 UTC

*** This bug has been marked as a duplicate of bug 656492 ***