-
Notifications
You must be signed in to change notification settings - Fork 37.7k
rpc: use CScheduler for HTTPRPCTimer #32796
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
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/32796. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
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.
lgtm ACK 7bc20b1
Could start title with rpc:
?
7bc20b1
to
466722c
Compare
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.
lgtm ACK 466722c 🎱
Show signature
Signature:
untrusted comment: signature from minisign secret key on empty file; verify via: minisign -Vm "${path_to_any_empty_file}" -P RWTRmVTMeKV5noAMqVlsMugDDCyyTSbA3Re5AkUrhvLVln0tSaFWglOw -x "${path_to_this_whole_four_line_signature_blob}"
RUTRmVTMeKV5npGrKx1nqXCw5zeVHdtdYURB/KlyA/LMFgpNCs+SkW9a8N95d+U4AP1RJMi+krxU1A3Yux4bpwZNLvVBKy0wLgM=
trusted comment: lgtm ACK 466722cbe5d6c9ddf35d1590b749d19ec115684e 🎱
BIFmQ7bHKY+gQInqAOOTQFAXFxXQJHAH2aGv/XMhziokLGtp5GIeKdYYzaDYg9TthqPZmgwLUlYlQk4qGLzXDg==
test/functional/wallet_keypool.py
Outdated
# CScheduler relies on condition_variable::wait_until() which is slightly | ||
# less accurate than libevent's event trigger. We'll give it 2 | ||
# seconds to execute a 1 second scheduled event. | ||
time.sleep(2) |
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 this turns out problematic (intermittently fail), one could also try mockscheduler
.
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.
Good idea, but would that reduce confidence in the test coverage for RPCRunLater()
etc?
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.
Just for additional reference, the check is already sometimes failing on current master: #30797 (comment)
466722c
to
e70c208
Compare
re-ACK e70c208 💱 Show signatureSignature:
|
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.
Concept ACK
test/functional/wallet_keypool.py
Outdated
@@ -127,7 +127,10 @@ def run_test(self): | |||
nodes[0].keypoolrefill(3) | |||
|
|||
# test walletpassphrase timeout | |||
time.sleep(1.1) | |||
# CScheduler relies on condition_variable::wait_until() which is slightly | |||
# less accurate than libevent's event trigger. We'll give it 2 |
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.
Seems weird to mention libevent here as a point of reference since it's in the past after this change is applied. I would put this in the commit message and just say that it's not accurate enough here.
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 I'll remove reference to libevent (thats the whole point anyway!) and explain why there is a margin of error in the test
src/httprpc.cpp
Outdated
}; | ||
|
||
class HTTPRPCTimerInterface : public RPCTimerInterface | ||
{ | ||
public: | ||
explicit HTTPRPCTimerInterface(struct event_base* _base) : base(_base) | ||
explicit HTTPRPCTimerInterface(const std::any& context) | ||
: m_context{*Assert(std::any_cast<NodeContext*>(context))} |
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.
Did you consider avoiding the dependency to node context and just give the Inteface it's own CScheduler
instead?
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.
Good feedback I think you're right, its cleaner to just store a reference to the scheduler here. It requires some weird pointer / any
juggling inStartHTTPRPC()
-- to keep the std::any
abstraction
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.
ACK e70c208
Would be nice to take #32796 (comment)
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.
ACK e70c208
PR makes a step to remove the dependency on libevent, this pr removes the dependency in the wallet re-locking functionality.
(I do agree with NIT comments above and hope to see #32796 (comment) included)
- code review ✅
- ran test ✅
This removes the dependency on libevent for scheduled events, like re-locking a wallet some time after decryption.
e70c208
to
d06942c
Compare
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.
src/httprpc.cpp
Outdated
}; | ||
|
||
class HTTPRPCTimerInterface : public RPCTimerInterface | ||
{ | ||
public: | ||
explicit HTTPRPCTimerInterface(struct event_base* _base) : base(_base) | ||
explicit HTTPRPCTimerInterface(const std::any& context) | ||
: m_context{*Assert(std::any_cast<NodeContext*>(context))} |
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.
Good feedback I think you're right, its cleaner to just store a reference to the scheduler here. It requires some weird pointer / any
juggling inStartHTTPRPC()
-- to keep the std::any
abstraction
test/functional/wallet_keypool.py
Outdated
@@ -127,7 +127,10 @@ def run_test(self): | |||
nodes[0].keypoolrefill(3) | |||
|
|||
# test walletpassphrase timeout | |||
time.sleep(1.1) | |||
# CScheduler relies on condition_variable::wait_until() which is slightly | |||
# less accurate than libevent's event trigger. We'll give it 2 |
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 I'll remove reference to libevent (thats the whole point anyway!) and explain why there is a margin of error in the test
Code review ACK d06942c |
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.
ACK d06942c
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.
re ACK d06942c
Changes sinds last ACK:
Included suggestions (thanks) to change:
- moved away from
std::any
abstraction in theHTTPRPCTimerInterface
- changed testing
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 the scheduler
is also used for the validation signals (see here), using it for RPC as well seems likely to delay block processing — we only allow up to 10 queued tasks at a time before pausing block processing (see here).
So, in other words, adding 10 long-lived timers through RPC could end up blocking block processing entirely?
Haven't tested it but it seems to be the case. Probably better to use a different scheduler for RPC timers.
Update:
Just discussed this offline with @pinheadmz, and it turns out there's a separate list for validation signal events. So the pending callbacks limit only affects that list, not the underlying scheduler queue size. This makes it less of a problem than I initially thought.
That said, the scheduler still runs the worker thread that executes the validation signal events, so adding more tasks to it doesn’t seem ideal. It might be better to use a separate scheduler for RPC. Or maybe in a follow-up?
@furszy I think it makes more sense to move the validation signals to their own scheduler thread if we are really concerned scheduled events will slow down block validation. We can also run some benchmarks, ie unlock 1000 wallets during IBD and try to evaluate the impact on validation signals. @maflcko do you have any instincts about this? |
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.
ACK d06942c
I think it makes more sense to move the validation signals to their own scheduler thread if we are really concerned scheduled events will slow down block validation. walletpassphrase is currently the only RPC that schedules a new event, so all this PR will add to the queue are calls to CWallet::Lock() after the user needs a private key
Sounds fair to me.
Edit: It's the same |
Interesting, I can try that approach... for that matter, could we rip out |
@achow101 I started working on calling |
This behavior would already be changing in this PR. Deleting the
This behavior would still be maintained even if the task runs multiple times because there is an explicit check in the relock function for whether the current run of that function is actually the most recently scheduled relock. |
bitcoin/src/wallet/rpc/encrypt.cpp Lines 103 to 104 in a92e8b1
🤦 yup clear as day thanks |
Opened #32862 with the suggested approach, closing this in favor of that. |
…Timer fcfd3db remove RPCTimerInterface and RPCRunLater (Matthew Zipkin) 8a17657 use WalletContext scheduler for walletpassphrase callback (Matthew Zipkin) Pull request description: This removes the dependency on libevent for events scheduled by RPC commands, like re-locking a wallet some time after decryption with walletpassphrase. Since walletpassphrase is currently the only RPC that does this, `RPCRunLater`, `RPCTimerInterface` and all related methods are left unused, and deleted in the second commit. Any future RPC that needs to execute a callback in the future can follow the pattern in this PR and just use a scheduler from node or wallet context. This is an alternative approach to #32796, described in #32796 (comment) ACKs for top commit: fjahr: Code Review ACK fcfd3db achow101: ACK fcfd3db furszy: ACK fcfd3db Tree-SHA512: 04f5e9c3f73f598c3d41d6e35bb59c64c7b93b03ad9fce3c40901733147ce7764f41f475fef1527d44af18f722759996a31ca83b48cb52153795d5022fecfd14
This removes the dependency on libevent for events scheduled by RPC commands, like re-locking a wallet some time after decryption with
walletpassphrase
.This PR is cherry-picked from #32061 and is part of removing libevent from the project
This does result in a slightly less reliable timing compared to libevent as described in #32793. In the test I added a little bit more time for the event to execute. I don't think this a big deal but reviewers lemme know what you think.