aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-10-26 20:02:16 +0100
committerFelix Morgner <felix.morgner@gmail.com>2026-10-26 20:02:16 +0100
commitf3b1c84a29e272cc589c300bca5020ccd4685a02 (patch)
treeabe08cad4277c76a799e98f7f66cf866580ae31f
parent1adf2896e3606ecb03785f96af786d891e564ed1 (diff)
downloadttwhy-f3b1c84a29e272cc589c300bca5020ccd4685a02.tar.xz
ttwhy-f3b1c84a29e272cc589c300bca5020ccd4685a02.zip
terminal: fix signal handling state restore
-rw-r--r--ttwhy/terminal/scoped_attributes.cppm29
-rw-r--r--ttwhy/terminal/signal_handling.cppm3
2 files changed, 31 insertions, 1 deletions
diff --git a/ttwhy/terminal/scoped_attributes.cppm b/ttwhy/terminal/scoped_attributes.cppm
index 56fbe58..2d82826 100644
--- a/ttwhy/terminal/scoped_attributes.cppm
+++ b/ttwhy/terminal/scoped_attributes.cppm
@@ -150,9 +150,38 @@ namespace ttwhy::terminal
return std::move(*this);
}
+ //! Capture the currently active terminal mode and mark the attributes as suspended.
+ //!
+ //! Must be called before the terminal mode is changed while the process is being stopped.
+ auto suspend() & -> scoped_attributes &
+ {
+ if (m_file_descriptor > 0)
+ {
+ m_suspended = true;
+ m_suspended_canonical = canonical_mode();
+ m_suspended_echo = echo();
+ }
+ return *this;
+ }
+
+ //! Restore the terminal mode captured before suspension.
+ auto resume() & -> scoped_attributes &
+ {
+ if (m_suspended)
+ {
+ canonical_mode(m_suspended_canonical);
+ echo(m_suspended_echo);
+ m_suspended = false;
+ }
+ return *this;
+ }
+
private:
int m_file_descriptor;
termios m_attributes;
+ bool m_suspended{false};
+ bool m_suspended_canonical{false};
+ bool m_suspended_echo{false};
};
} // namespace ttwhy::terminal
diff --git a/ttwhy/terminal/signal_handling.cppm b/ttwhy/terminal/signal_handling.cppm
index b0a3542..2921b96 100644
--- a/ttwhy/terminal/signal_handling.cppm
+++ b/ttwhy/terminal/signal_handling.cppm
@@ -49,13 +49,14 @@ namespace ttwhy::terminal
}
case SIGTSTP:
{
+ attributes.suspend();
attributes.canonical_mode(true).echo(true);
::raise(SIGSTOP);
break;
}
case SIGCONT:
{
- attributes.canonical_mode(false).echo(false);
+ attributes.resume();
break;
}
}