Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/geth, console: support interrupting the js console #23387

Merged
merged 17 commits into from
Dec 11, 2021

Conversation

holiman
Copy link
Contributor

@holiman holiman commented Aug 12, 2021

This PR changes the behavior of Ctrl-C (i.e. SIGINT) when the console is active.
Previously, this signal was ignored during JS execution, so it was not possible
to get out of infinite loops in the console. With this change, Ctrl-C now
interrupts JS.

Fixes #23344

@holiman
Copy link
Contributor Author

holiman commented Aug 26, 2021

Not sure what happens there...

Regarding that...

Local console, eternal loop, hit ctrl-c:

  • With this PR, geth (almost fully) shuts down and the operation is aborted. User is put back into the console (with a dead blockchain) and can ctrl-d to exit.
  • Master: geth shuts down, is prevented from doing so, and eventually needs to be panic:ed
  • Desired: operation is aborted, geth does not shut down

So, even for that case, this PR is better than master.

What actually happens, though, is that since we're not in console reading mode any more, the ctrl-c handling is done in the geth normal handler, so that's what triggers the shutdown.

@holiman
Copy link
Contributor Author

holiman commented Aug 26, 2021

With this PR, geth (almost fully) shuts down and the operation is aborted. User is put back into the console (with a dead blockchain) and can ctrl-d to exit.

This has now been improved.

Local console, eternal loop, hit ctrl-c:

  • With this PR, geth shuts down, the operation is aborted and geth exits gracefully.
  • Master: geth shuts down, is prevented from doing so, and eventually needs to be panic:ed
  • Desired behaviour: operation is aborted, geth does not shut down
To exit, press ctrl-d
> while(true){}
^C> INFO [08-26|13:53:51.952] Got interrupt, shutting down... 
aborted by caller at <eval>:1:1(3)
INFO [08-26|13:53:51.953] IPC endpoint closed                      url=/tmp/geth.ipc
INFO [08-26|13:53:51.953] Ethereum protocol stopped 
INFO [08-26|13:53:51.953] Transaction pool stopped 
INFO [08-26|13:53:51.953] Writing snapshot state to disk           root=2c6528..bde715
INFO [08-26|13:53:51.953] Persisted trie from memory database      nodes=0  size=0.00B   time="5.323µs" gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00B
INFO [08-26|13:53:51.953] Blockchain stopped 
exiting console

@holiman
Copy link
Contributor Author

holiman commented Oct 11, 2021

ping @gballet PTAL?

@fjl
Copy link
Contributor

fjl commented Oct 12, 2021

I have some ideas for this, please don't merge it yet.

@s1na
Copy link
Contributor

s1na commented Dec 1, 2021

@fjl was curious what your idea was regarding this PR

@fjl
Copy link
Contributor

fjl commented Dec 2, 2021

I tried to implement the proper semantics where geth doesn't shut down on Ctrl-C. It's a bit complicated though.
My idea was refactoring the geth interrupt handler so that it wouldn't be active in console mode.

@s1na
Copy link
Contributor

s1na commented Dec 2, 2021

I was getting a crash immediately during start. I couldn't figure out where it came from but after a rebase against master the crash is gone

@s1na
Copy link
Contributor

s1na commented Dec 2, 2021

My idea was refactoring the geth interrupt handler so that it wouldn't be active in console mode.

I tried your idea here. It works. I thought sigterm should still cause shutdown. Do you agree with that? if so I need to change the code a bit because right now if first a sigint arrives and we're in console mode any future sigterm is ignored.

Update: fixed sigterm handling here. So now ctrl+c only stops while(true) but kill <pid> stops while(true) and shuts geth down gracefully.

@s1na
Copy link
Contributor

s1na commented Dec 3, 2021

@holiman can you please take a look at my changes whenever you get a chance and tell me if its okay for me to push them to your branch?

@holiman
Copy link
Contributor Author

holiman commented Dec 3, 2021

I find it a bit hard to follow, can't compare across forks, since you rebased mine before you committed yours. Do you think you can push the rebased to my repo for easier comparison?

Edit: or squash your two commits into one?

cmd: fix sigterm handling in console mode
@s1na
Copy link
Contributor

s1na commented Dec 3, 2021

Yes squashed: s1na@0e99d3f

@holiman
Copy link
Contributor Author

holiman commented Dec 3, 2021

LGTM, push it here why dontcha?

@holiman
Copy link
Contributor Author

holiman commented Dec 6, 2021

Yup, with your fixes, this now works for me:

[user@work go-ethereum]$ ./build/bin/geth --dev console
...
Welcome to the Geth JavaScript console!

instance: Geth/v1.10.14-unstable-46891a6b-20211203/linux-amd64/go1.17.3
coinbase: 0xc9493a99d64c05dbfcf6635a52aa7a990f0250bc
at block: 0 (Thu Jan 01 1970 01:00:00 GMT+0100 (CET))
 datadir: 
 modules: admin:1.0 clique:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

To exit, press ctrl-d or type exit
> while(true){}
^C> aborted by caller at <eval>:1:1(1)

@fjl
Copy link
Contributor

fjl commented Dec 6, 2021

I will re-check and merge later today!

@fjl fjl self-assigned this Dec 6, 2021
Better to pass this in from cmd/geth, which knows if it's running
the console or not.
This reimplements the interrupt so that it always works. The previous
implementation only worked for Interactive.
Fatalf doesn't shut down the node properly.
Calling it multiple times should not crash. Also move history writing
into Interactive, where it belongs.
@fjl
Copy link
Contributor

fjl commented Dec 7, 2021

I've tested this extensively and decided to rework the interrupt logic a bit more to
really handle all the cases. In some of the cases listed below, the JS interrupt did not
work or caused an unclean shutdown of the node.

./geth console --dev

> partialInput^
# when SIGTERM received, geth should exit
# when SIGINT received, it should not exit
# when Ctrl-C, it should clear the line
./geth console --dev

> while(true) { admin.sleep(1); console.log("sleeping"); }
sleeping
sleeping
^
# when SIGTERM received, geth should exit
# when SIGINT received or Ctrl-C, it should return to JS prompt
TERM=dumb ./geth console --dev

> partialInput^
# special case: when Ctrl-C/SIGINT, geth should exit
TERM=dumb ./geth console --dev

> while(true) { admin.sleep(1); console.log("sleeping"); }
sleeping
sleeping
^
# when SIGTERM received, geth should exit
# when SIGINT received or Ctrl-C, it should return to JS prompt
./geth console --dev --exec 'while(true) { admin.sleep(1); console.log("sleeping"); }'
sleeping
sleeping
^
# SIGTERM/SIGINT/Ctrl-C should interrupt JS and shut down the node
echo 'while(true) { admin.sleep(1); console.log("sleeping"); }' > loop1.js
./geth --dev js loop1.js
sleeping
sleeping
^
# SIGTERM/SIGINT/Ctrl-C should interrupt JS and shut down the node

@fjl fjl removed their assignment Dec 7, 2021
@holiman
Copy link
Contributor Author

holiman commented Dec 7, 2021

LGTM. While testing this, I had some issues with the history, things didn't seem to be added to it. Then I cleared out the history (there were 1923 lines in it), and tried to repro it, but suddenly things started to work after that, so not sure what it was.

@fjl
Copy link
Contributor

fjl commented Dec 7, 2021

I need to recheck my change to the history write. Maybe it doesn't work properly now.

@fjl fjl changed the title cmd/geth, console: support interrupting the js engine, fixes #23344 cmd/geth, console: support interrupting the js console Dec 11, 2021
@fjl fjl merged commit 72c2c0a into ethereum:master Dec 11, 2021
@fjl fjl removed the status:triage label Dec 11, 2021
@fjl fjl added this to the 1.10.14 milestone Dec 11, 2021
@fjl
Copy link
Contributor

fjl commented Dec 11, 2021

I checked the history behavior and it seems to work.

JacekGlen pushed a commit to JacekGlen/go-ethereum that referenced this pull request May 26, 2022
Previously, Ctrl-C (SIGINT) was ignored during JS execution, so it was not
possible to get out of infinite loops in the console. With this change,
Ctrl-C now interrupts JS.

Fixes ethereum#23344

Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
Co-authored-by: Felix Lange <fjl@twurst.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Geth console unresponsive when running js statement
3 participants