Skip to content

WIP: readline: ctrl+c close stdin - #673

Draft
mdavidsaver wants to merge 1 commit into
epics-base:7.0from
mdavidsaver:sigint-readline
Draft

WIP: readline: ctrl+c close stdin#673
mdavidsaver wants to merge 1 commit into
epics-base:7.0from
mdavidsaver:sigint-readline

Conversation

@mdavidsaver

@mdavidsaver mdavidsaver commented Jul 6, 2025

Copy link
Copy Markdown
Member

My attempt at #670. Provokes readline() and getc() to return immediately, and so also interrupts interactive iocsh(NULL) . Only interrupts iocsh(NULL), just as an exit iocsh command currently does. Depends on IOC skeleton to

Consequential differences with #671.

  • Does not call epicsExit().
  • Instead of close(0), uses dup2() to atomically replace stdin with /dev/null to avoid potential race with re-use of FD zero.
  • Avoids a new worker thread
  • Signal handler only installed while waiting for input. Same as libreadline, so no new scope for conflicts.
  • Uses sigaction() to also save/restore handler flags.
  • Set SA_RESETHAND handler flag so that a repeated signal will trigger the default handler.
  • No changes to thread signal masks. (does not matter which thread runs this handler)

Unnecessary differences, which could/should be removed.

  • A bunch of calls to fprintf() for troubleshooting, which is not signal-safe.
  • Clones, and later replaces, original stdin after interruption. Theoretically allows calling iocsh(NULL) in a loop with multiple interruptions.
    • Second dup2() to restore stdin loses FD flags. (could save/restore flags as well)
  • Set SA_RESTART flag to approximate BSD behavior. Maybe reduces testing matrix.
  • Does not handle SIGTERM.

@mdavidsaver

mdavidsaver commented Jul 6, 2025

Copy link
Copy Markdown
Member Author

@dirk-zimoch I wrote this code as I do not think I was explaining myself properly in the #671 thread. I am happy to leave this PR as an example.

@AppVeyorBot

Copy link
Copy Markdown

@mdavidsaver

Copy link
Copy Markdown
Member Author

fyi. testing with modified ralphlange/procServ#70 with --grace-period argument.

./procServ -d -f --killsig 2 --grace-period 3 5678 ~/epics/base-git/bin/linux-x86_64/softIoc
...
epics> var atExitDebug 1

Concurrent killall -TERM procServ triggers:

epics> SigTerm received
Sending signal 2 to pid 802292
Start child cleanup timer 3 sec.
atExit errlogExitHandler(0x55e14e855930)
atExit rlExit((nil))
atExit syncShutdown((nil))
atExit decShutdown((nil))
atExit dbndShutdown((nil))
atExit arrShutdown((nil))
processItem: Got error reading input connection: Input/output error

@@@ @@@ @@@ @@@ @@@
@@@ Received a sigChild for process 802292. Normal exit status = 0
Deleting connection 0x55a192657c90
@@@ Current time: Sun Jul  6 17:02:01 2025
@@@ Child process is shutting down, oneshot mode: server will exit
~connectionItem()
child exits
Close sockets
~clientItem(); handle 0 closed
~connectionItem()
~acceptItem()
~connectionItem()
Cleanup pid and info files

Provokes readline() and getc() to return immediately,
and so also interrupts interactive iocsh(NULL) .
@codacy-production

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 1 high · 2 medium

Alerts:
⚠ 3 issues (≤ 0 issues of at least minor severity)

Results:
3 new issues

Category Results
UnusedCode 2 medium
Security 1 high

View in Codacy

🟢 Metrics 6 complexity

Metric Results
Complexity 6

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@mdavidsaver

Copy link
Copy Markdown
Member Author

Rebased with no changes. My casual testing over the past year has not turned up any misbehavior.

@AppVeyorBot

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants