Skip to content

Commit 8c2b5d2

Browse files
daveppablogsal
andcommitted
Only perform the SIGTOU test if we're hooked up to a tty
Fixes #4104 Co-authored-by: Pablo Galindo <[email protected]>
1 parent 8ae0b27 commit 8c2b5d2

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

src/textual/drivers/linux_driver.py

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -156,28 +156,33 @@ def _stop_again(*_) -> None:
156156
"""Signal handler that will put the application back to sleep."""
157157
os.kill(os.getpid(), signal.SIGSTOP)
158158

159-
# Set up handlers to ensure that, if there's a SIGTTOU or a SIGTTIN,
160-
# we go back to sleep.
161-
signal.signal(signal.SIGTTOU, _stop_again)
162-
signal.signal(signal.SIGTTIN, _stop_again)
163-
try:
164-
# Here we perform a NOP tcsetattr. The reason for this is that,
165-
# if we're suspended and the user has performed a `bg` in the
166-
# shell, we'll SIGCONT *but* we won't be allowed to do terminal
167-
# output; so rather than get into the business of spinning up
168-
# application mode again and then finding out, we perform a
169-
# no-consequence change and detect the problem right away.
170-
termios.tcsetattr(
171-
self.fileno, termios.TCSANOW, termios.tcgetattr(self.fileno)
172-
)
173-
except termios.error:
174-
# There was an error doing the tcsetattr; there is no sense in
175-
# carrying on because we'll be doing a SIGSTOP (see above).
176-
return
177-
finally:
178-
# We don't need to be hooking SIGTTOU or SIGTTIN any more.
179-
signal.signal(signal.SIGTTOU, signal.SIG_DFL)
180-
signal.signal(signal.SIGTTIN, signal.SIG_DFL)
159+
# If we're working with an actual tty...
160+
# https://github.com/Textualize/textual/issues/4104
161+
if os.isatty(self.fileno):
162+
# Set up handlers to ensure that, if there's a SIGTTOU or a SIGTTIN,
163+
# we go back to sleep.
164+
signal.signal(signal.SIGTTOU, _stop_again)
165+
signal.signal(signal.SIGTTIN, _stop_again)
166+
try:
167+
# Here we perform a NOP tcsetattr. The reason for this is
168+
# that, if we're suspended and the user has performed a `bg`
169+
# in the shell, we'll SIGCONT *but* we won't be allowed to
170+
# do terminal output; so rather than get into the business
171+
# of spinning up application mode again and then finding
172+
# out, we perform a no-consequence change and detect the
173+
# problem right away.
174+
termios.tcsetattr(
175+
self.fileno, termios.TCSANOW, termios.tcgetattr(self.fileno)
176+
)
177+
except termios.error:
178+
# There was an error doing the tcsetattr; there is no sense
179+
# in carrying on because we'll be doing a SIGSTOP (see
180+
# above).
181+
return
182+
finally:
183+
# We don't need to be hooking SIGTTOU or SIGTTIN any more.
184+
signal.signal(signal.SIGTTOU, signal.SIG_DFL)
185+
signal.signal(signal.SIGTTIN, signal.SIG_DFL)
181186

182187
loop = asyncio.get_running_loop()
183188

0 commit comments

Comments
 (0)