GNU bug report logs

#57095 'terminal-window-size' throws ENOTTY ("Inappropriate ioctl for device")

PackageSource(s)Maintainer(s)
guix PTS Buildd Popcon
Reply or subscribe to this bug. View this bug as an mbox, status mbox, or maintainer mbox

Report forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Tue, 09 Aug 2022 23:13:02 GMT) (full text, mbox, link).


Acknowledgement sent to Csepp <raingloom@riseup.net>:
New bug report received and forwarded. Copy sent to bug-guix@gnu.org. (Tue, 09 Aug 2022 23:13:02 GMT) (full text, mbox, link).


Message #5 received at submit@debbugs.gnu.org (full text, mbox, reply):

From: Csepp <raingloom@riseup.net>
To: bug-guix@gnu.org
Subject: another "inappropriate ioctl" bug :)
Date: Tue, 09 Aug 2022 23:06:11 +0000
```
./pre-inst-env guix import pypi -r linode-cli | tee -a gnu/packages/python-xyz.scm

...
In guix/build/syscalls.scm:
  2284:35  1 (_)
   2273:8  0 (terminal-window-size _)

guix/build/syscalls.scm:2273:8: In procedure terminal-window-size:
In procedure terminal-window-size: Inappropriate ioctl for device
```

I assume the progress bar code does not gracefully handle the very
common case when stdout is not a terminal.

Good thing I'm in a local checkout so I can just make it return some
constant.




Changed bug title to ''terminal-window-size' throws ENOTTY ("Inappropriate ioctl for device")' from 'another "inappropriate ioctl" bug :)' Request was from Ludovic Courtès <ludo@gnu.org> to control@debbugs.gnu.org. (Wed, 10 Aug 2022 13:39:02 GMT) (full text, mbox, link).


Information forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Wed, 10 Aug 2022 13:44:02 GMT) (full text, mbox, link).


Message #10 received at 57095@debbugs.gnu.org (full text, mbox, reply):

From: Josselin Poiret <dev@jpoiret.xyz>
To: Csepp <raingloom@riseup.net>, 57095@debbugs.gnu.org
Subject: Re: bug#57095: another "inappropriate ioctl" bug :)
Date: Wed, 10 Aug 2022 15:43:18 +0200
Hi!

Csepp <raingloom@riseup.net> writes:

> ```
> ./pre-inst-env guix import pypi -r linode-cli | tee -a gnu/packages/python-xyz.scm
>
> ...
> In guix/build/syscalls.scm:
>   2284:35  1 (_)
>    2273:8  0 (terminal-window-size _)
>
> guix/build/syscalls.scm:2273:8: In procedure terminal-window-size:
> In procedure terminal-window-size: Inappropriate ioctl for device
> ```
>
> I assume the progress bar code does not gracefully handle the very
> common case when stdout is not a terminal.

There is some code in place to handle this issue, and it works most of
the time, but not here.  The issue is that we handle any error coming
from ioctl by first throwing a `'system-error`, and handling it with a
`catch` that checks whether the errno is ENOTTY (and deprecated
equivalents) and in that case falls back to a good default.  In the case
where the error is not of that type, it is rethrown.  This works well in
most cases, but here comes the Guile shenanigans:

We also use a big wrapping `with-error-handling` to display errors
properly in the case when they are not caught.  The difference is that
`with-error-handling` adds a non-unwinding handler, while catch is
unwinding.  My first thought was that non-unwinding handlers, even outer
ones would get priority over unwinding ones, since once the stack's
unwound you can't really go back (I have no idea if that last part is
actually true).  In practice this is actually false, I tested with a
very simple example, but that lead me to test by setting `#:unwind? #t`
for the `guard*` definition in guix/ui.scm and the issue went away, so I'm
clueless as to why this happens.  What seems weird is that the error is
not caught at all!

Does anyone have a clue?

Best,
-- 
Josselin Poiret




Information forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Wed, 10 Aug 2022 14:54:01 GMT) (full text, mbox, link).


Message #13 received at 57095@debbugs.gnu.org (full text, mbox, reply):

From: Ludovic Courtès <ludo@gnu.org>
To: Josselin Poiret <dev@jpoiret.xyz>
Cc: 57095@debbugs.gnu.org, Csepp <raingloom@riseup.net>
Subject: Re: bug#57095: another "inappropriate ioctl" bug :)
Date: Wed, 10 Aug 2022 16:53:29 +0200
Hi!

Josselin Poiret <dev@jpoiret.xyz> skribis:

> We also use a big wrapping `with-error-handling` to display errors
> properly in the case when they are not caught.  The difference is that
> `with-error-handling` adds a non-unwinding handler, while catch is
> unwinding.  My first thought was that non-unwinding handlers, even outer
> ones would get priority over unwinding ones, since once the stack's
> unwound you can't really go back (I have no idea if that last part is
> actually true).  In practice this is actually false, I tested with a
> very simple example, but that lead me to test by setting `#:unwind? #t`
> for the `guard*` definition in guix/ui.scm and the issue went away, so I'm
> clueless as to why this happens.  What seems weird is that the error is
> not caught at all!

The inner handler, even if it’s unwinding and the outer one is not,
appears to have higher precedence:

--8<---------------cut here---------------start------------->8---
scheme@(guix read-print)> (with-exception-handler (lambda args (pk 'outer args))
			    (lambda ()
			      (with-exception-handler
				  (lambda args (pk 'inner args))
				(lambda()
				  (rmdir "/"))
				#:unwind? #t))
			    #:unwind? #f)

;;; (inner (#<&compound-exception components: (#<&external-error> #<&origin origin: "rmdir"> #<&message message: "~A"> #<&irritants irritants: ("Device or resource busy")> #<&exception-with-kind-and-args kind: system-error args: ("rmdir" "~A" ("Device or resource busy") (16))>)>))
$17 = (#<&compound-exception components: (#<&external-error> #<&origin origin: "rmdir"> #<&message message: "~A"> #<&irritants irritants: ("Device or resource busy")> #<&exception-with-kind-and-args kind: system-error args: ("rmdir" "~A" ("Device or resource busy") (16))>)>)
scheme@(guix read-print)> (with-exception-handler (lambda args (pk 'outer args))
			    (lambda ()
			      (catch 'system-error
				(lambda ()
				  (rmdir "/"))
				(lambda args
				  (pk 'inner args))))
			    #:unwind? #f)

;;; (inner (system-error "rmdir" "~A" ("Device or resource busy") (16)))
$18 = (system-error "rmdir" "~A" ("Device or resource busy") (16))
--8<---------------cut here---------------end--------------->8---

This appears to work:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)> ,use(guix build syscalls)
scheme@(guile-user)> (terminal-columns)
$19 = 119
scheme@(guile-user)> ,use(guix ui)
scheme@(guile-user)> (with-error-handling (terminal-columns))
$20 = 119
scheme@(guile-user)> (terminal-columns (open-input-string ""))
$21 = 143
scheme@(guile-user)> (with-error-handling (terminal-columns (open-input-string "")))
$22 = 143
--8<---------------cut here---------------end--------------->8---

Needs more investigation…

Ludo’.




Severity set to 'important' from 'normal' Request was from Ludovic Courtès <ludo@gnu.org> to control@debbugs.gnu.org. (Mon, 29 Aug 2022 13:02:01 GMT) (full text, mbox, link).


Information forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Thu, 01 Sep 2022 21:05:01 GMT) (full text, mbox, link).


Message #18 received at 57095@debbugs.gnu.org (full text, mbox, reply):

From: Ludovic Courtès <ludo@gnu.org>
To: Josselin Poiret <dev@jpoiret.xyz>
Cc: 57095@debbugs.gnu.org, Csepp <raingloom@riseup.net>
Subject: Re: bug#57095: 'terminal-window-size' throws ENOTTY ("Inappropriate ioctl for device")
Date: Thu, 01 Sep 2022 23:04:35 +0200
Hi,

Josselin Poiret <dev@jpoiret.xyz> skribis:

> We also use a big wrapping `with-error-handling` to display errors
> properly in the case when they are not caught.  The difference is that
> `with-error-handling` adds a non-unwinding handler, while catch is
> unwinding.  My first thought was that non-unwinding handlers, even outer
> ones would get priority over unwinding ones, since once the stack's
> unwound you can't really go back (I have no idea if that last part is
> actually true).  In practice this is actually false, I tested with a
> very simple example, but that lead me to test by setting `#:unwind? #t`
> for the `guard*` definition in guix/ui.scm and the issue went away, so I'm
> clueless as to why this happens.  What seems weird is that the error is
> not caught at all!

Here’s a reproducer:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)>  (with-exception-handler (lambda _ (catch 'x (lambda () (throw 'x)) (const 'good) ))
			 (lambda ()
			   (rmdir "/"))
			 #:unwind? #f)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Throw to key `x' with args `()'.
--8<---------------cut here---------------end--------------->8---

Or, simplified:

--8<---------------cut here---------------start------------->8---
scheme@(guile-user)>  (with-exception-handler
			  (lambda _ (with-exception-handler (const 'good)
				      (lambda () (throw 'x))
				      #:unwind? #t))
			 (lambda ()
			   (rmdir "/"))
			 #:unwind? #f)
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Throw to key `x' with args `()'.
--8<---------------cut here---------------end--------------->8---

We expect 'x to be caught, leading the handler to return 'good.
Instead, 'x is not caught at all.

In both cases, setting #:unwind? #t in the outer
‘with-exception-handler’ gives the expected result.

I spent some time staring at the relevant code in ‘boot-9.scm’ but
nothing came out of it.

Ludo’.




Information forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Thu, 01 Sep 2022 21:22:02 GMT) (full text, mbox, link).


Message #21 received at 57095@debbugs.gnu.org (full text, mbox, reply):

From: Maxime Devos <maximedevos@telenet.be>
To: Ludovic Courtès <ludo@gnu.org>, Josselin Poiret <dev@jpoiret.xyz>
Cc: 57095@debbugs.gnu.org, Csepp <raingloom@riseup.net>
Subject: Re: bug#57095: 'terminal-window-size' throws ENOTTY ("Inappropriate ioctl for device")
Date: Thu, 1 Sep 2022 23:21:45 +0200
[Message part 1 (text/plain, inline)]
On 01-09-2022 23:04, Ludovic Courtès wrote:
> [...]
> We expect 'x to be caught, leading the handler to return 'good.
> Instead, 'x is not caught at all.
>
> In both cases, setting #:unwind? #t in the outer
> ‘with-exception-handler’ gives the expected result.
>
> I spent some time staring at the relevant code in ‘boot-9.scm’ but
> nothing came out of it.
>
> Ludo’.
>
>
Maybe my answer on IRC is relevant here:

https://logs.guix.gnu.org/guile/2022-09-01.log#231503

Greetings,
Maxime.

[OpenPGP_0x49E3EE22191725EE.asc (application/pgp-keys, attachment)]
[OpenPGP_signature (application/pgp-signature, attachment)]

Information forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Fri, 02 Sep 2022 09:19:01 GMT) (full text, mbox, link).


Message #24 received at 57095@debbugs.gnu.org (full text, mbox, reply):

From: Ludovic Courtès <ludo@gnu.org>
To: Maxime Devos <maximedevos@telenet.be>
Cc: 57095@debbugs.gnu.org, Josselin Poiret <dev@jpoiret.xyz>, Csepp <raingloom@riseup.net>
Subject: Re: bug#57095: 'terminal-window-size' throws ENOTTY ("Inappropriate ioctl for device")
Date: Fri, 02 Sep 2022 11:17:55 +0200
Hi,

Maxime Devos <maximedevos@telenet.be> skribis:

> Maybe my answer on IRC is relevant here:
>
> https://logs.guix.gnu.org/guile/2022-09-01.log#231503

Interesting.

It’s a Guile bug, and a tricky one.  Here’s what Andy wrote on IRC:

<sneek> civodul, wingo says: i believe it is a bug.  in a pre-unwind handler,
	you want to make it so that if it throws again, it is handled by the
	handler that was current when the with-exception-handler was invoked
	(the dynamically outer handler)
<sneek> civodul, wingo says: to implement this, when a throw first starts, we
	capture the current handler stack, and arrange for subsequent throws
	to resolve via that captured handler stack
<sneek> civodul, wingo says: but if there is an additional
	with-exception-handler within the exception handler, that doesn't
	augment the captured exception handler stack to which inner exceptions
	will dispatch
<sneek> civodul, wingo says: the fix will be small but also gnarly :P  will
	take some thinking.  there are funny interactions with delimited
	continuations

I’ll defer to Andy to see what the best way to fix it is…

What’s frustrating is that I can’t think of a way to work around it,
except by changing ‘terminal-columns’ & co. to not use exceptions (or
introducing a variant that does that).

Thoughts?

Ludo’.




Information forwarded to bug-guix@gnu.org:
bug#57095; Package guix. (Fri, 02 Sep 2022 18:21:02 GMT) (full text, mbox, link).


Message #27 received at 57095@debbugs.gnu.org (full text, mbox, reply):

From: Maxime Devos <maximedevos@telenet.be>
To: Ludovic Courtès <ludo@gnu.org>
Cc: 57095@debbugs.gnu.org, Josselin Poiret <dev@jpoiret.xyz>, Csepp <raingloom@riseup.net>
Subject: Re: bug#57095: 'terminal-window-size' throws ENOTTY ("Inappropriate ioctl for device")
Date: Fri, 2 Sep 2022 20:14:44 +0200
[Message part 1 (text/plain, inline)]
On 02-09-2022 11:17, Ludovic Courtès wrote:
> [...]
>
> What’s frustrating is that I can’t think of a way to work around it,
> except by changing ‘terminal-columns’ & co. to not use exceptions (or
> introducing a variant that does that).
>
> Thoughts?

Exception handlers do not cross process boundaries. Maybe run the inner 
(catch ...) or (with-exception-handle ...) or whatever is used here in a 
separate thread + wait for the thread to return?

Greetings,
Maxime.

[OpenPGP_0x49E3EE22191725EE.asc (application/pgp-keys, attachment)]
[OpenPGP_signature (application/pgp-signature, attachment)]

Send a report that this bug log contains spam.


debbugs.gnu.org maintainers <help-debbugs@gnu.org>. Last modified: Sun Sep 8 03:06:01 2024; Machine Name: wallace-server

GNU bug tracking system

Debbugs is free software and licensed under the terms of the GNU Public License version 2. The current version can be obtained from https://bugs.debian.org/debbugs-source/.

Copyright © 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson, 2005-2017 Don Armstrong, and many other contributors.