-
Notifications
You must be signed in to change notification settings - Fork 649
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
Capture Ctrl+C in cli_wallet when not in daemon mode #1193 #1232
Conversation
IMO we should capture and treat SIGTERM the same as SIGINT. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't work for me - pressed CTRL-C and got message "Captured CTRL+C not in daemon mode", but wallet didn't exit.
I suspect that's because wallet_cli->stop internally calls the same wait() that is called by main.cpp, but https://github.com/bitshares/bitshares-fc/blob/master/src/thread/future.cpp#L107
programs/cli_wallet/main.cpp
Outdated
|
||
fc::set_signal_handler([&wallet_cli, &wapi, &wallet_file](int signal) { | ||
ilog( "Captured CTRL+C not in daemon mode" ); | ||
wapi->save_wallet_file(wallet_file.generic_string()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not required here, will be handled in line 302
programs/cli_wallet/main.cpp
Outdated
wapi->save_wallet_file(wallet_file.generic_string()); | ||
wallet_cli->stop(); | ||
std::terminate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Terminate? Why not exit
? (I want to know why but not simply asking for a change)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because exit
cannot finish program fully as terminate
can
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced that we should call this. Actually, I don't like exit
either, but IMHO terminate
is even worse. For example, why not raise SIGKILL
, I guess it can end the program as well, but all of them don't seem correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# abort
indicates "abnormal" end to the program, and raises the the POSIX signal SIGABRT, which means that any handler that you have registered for that signal will be invoked, although the program will still terminate afterwords in either case. Usually you would use abort in a C program to exit from an unexpected error case where the error is likely to be a bug in the program, rather than something like bad input or a network failure. For example, you might abort if a data structure was found to have a NULL pointer in it when that should logically never happen.
# exit
indicates a "normal" end to the program, although this may still indicate a failure (but not a bug). In other words, you might exit with an error code if the user gave input that could not be parsed, or a file could not be read. An exit code of 0 indicates success. exit also optionally calls handlers before it ends the program. These are registered with the atexit and on_exit functions.
#std::terminate
is what is automatically called in a C++ program when there is an unhandled exception. This is essentially the C++ equivalent to abort, assuming that you are reporting all your exceptional errors by means of throwing exceptions. This calls a handler that is set by the std::set_terminate function, which by default simply calls abort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do a "normal" end.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"normal" end won't fully terminate cli_wallet
This is what you need to figure out: how to end the program normally when needed.
Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cogutvalera I have explained above what the problem is, please try to solve instead of using dirty workarounds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://stackoverflow.com/questions/30250934/how-to-end-c-code
...but IMO exiting in any way is not the way to go here - just shut down wallet_cli cleanly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks !
Guys, check please when you will have enough time. Is cancel thread good enough ? Thanks ! |
I guess it's better, although the code looks a bit ugly. |
@abitmore Thank you very much ! I will think about it and how to improve the code ! |
Please explain why you don't shut down wallet_cli cleanly. |
@pmconrad please tell me what do you mean by do we have Thanks ! |
@cogutvalera I think we need code like |
@abitmore @pmconrad I've tried earlier Thanks ! |
3 weeks ago I wrote:
Try to work around this by adding a nowait=false parameter to stop, or something along that line. |
@pmconrad Thank you very much ! I've tried to work around earlier but nothing helped, will try again more to play with this approach as you suggested. Thanks ! |
e054b81
to
bed035f
Compare
rebased |
programs/cli_wallet/main.cpp
Outdated
fc::set_signal_handler([&wallet_cli, &wapi, &wallet_file](int signal) { | ||
ilog( "Captured SIGTERM not in daemon mode" ); | ||
wapi->save_wallet_file(wallet_file.generic_string()); | ||
wallet_cli->quit_blocked_thread(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found a simpler solution: just call fclose(stdin);
. Please test on Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks ! Will check it ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pmconrad I've checked your method on Ubuntu 18.04 and your solution is simpler than mine I absolutely agree with you but your solution has disadvantage:
after unlocking wallet if you press CTRL+C then you cannot see what you type in command line, you need to restart it, in my approach we don't have this issue.
Don't you like my approach by cleanly quitting blocked thread
?
Thanks !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I don't like that. :-)
- The thread may not be actually blocked at the time the signal is received. In that case your code will segfault.
- When compiled with editline, there is a separate background thread active that will be left dangling with your method.
I could not reproduce the behaviour you described, but it might be a good idea to restore tty settings when cli shuts down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cli_wallet
uses future
and promise
which has blocked_thread
member, when SIGINT
or SIGTERM
is caught I use method quit
of the blocked_thread
member, thus we will stop cli_wallet
's thread.
- What do you mean by "The thread may not be actually blocked at the time the signal is received" ?
- My solution just
quit
onlycli_wallet
's thread, do you mean my solution mayquit
another thread instead of required ? - To reproduce the behaviour I've described you should evaluate next 3 steps (tested on Ubuntu 18.04):
3.1. unlockcli_wallet
3.2 pressCTRL+C
3.3 try to write anything in command line tool and you won't see what are you typing there
Thanks !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- If the signal is received before you call wallet_cli->wait(), blocked_thread will be a nullptr. Admittedly this is unlikely in this specific case, but there may be other uses of fc::rpc::cli where it is less unlikely.
- No, there is another thread related to cli that is not stopped by your solution.
- I tried that (but not on Ubuntu). But never mind, if you see the behaviour then tty settings must be cleaned up. I suppose you do use editline? Can you reproduce this reliably?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used editline
through VS code and after new updates seems all works fine enough now with your solution @pmconrad (I mean fclose(stdin)
! Very simple and efficient ! Thank you very much ! Will do new commit now and will close next PR in fc
library bitshares/bitshares-fc#77 cause we don't need anymore
69eb872
to
e4b59b7
Compare
Please undo the fc bump in this PR and squash. |
ok sure ! Thanks ! |
e4b59b7
to
7dc0de7
Compare
Done ! Thank you ! |
Thanks! |
Thank you ! ;) |
@pmconrad should we merge this for 201810 feature release? I think we can do it. |
IMO we shouldn't include further issues once we have published the testnet release. Except for critical issues and bugs that are caught during testing of course. |
I agree with @pmconrad , some witnesses already installed new testnet version, announcements were made, etc. We should not push more changes to 201810 unless is absolutely necessary. We will always have stuff finished just one day after the release, we should left this and them out IMHO. |
Perhaps we should separate different releases in future for |
PR for #1193