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

multiprocess: Add basic spawn and IPC support #19160

Merged
merged 6 commits into from
Apr 27, 2021

Conversation

ryanofsky
Copy link
Contributor

@ryanofsky ryanofsky commented Jun 3, 2020

This PR is part of the process separation project.


This PR adds basic process spawning and IPC method call support to bitcoin-node executables built with --enable-multiprocess[*].

These changes are used in #10102 to let node, gui, and wallet functionality run in different processes, and extended in #19460 and #19461 after that to allow gui and wallet processes to be started and stopped independently and connect to the node over a socket.

These changes can also be used to implement new functionality outside the bitcoin-node process like external indexes or pluggable transports (#18988). The Ipc::spawnProcess and Ipc::serveProcess methods added here are entry points for spawning a child process and serving a parent process, and being able to make bidirectional, multithreaded method calls between the processes. A simple example of this is implemented in commit "Add echoipc RPC method and test."

Changes in this PR aside from the echo test were originally part of #10102, but have been split and moved here for easier review, and so they can be used for other applications like external plugins.

Additional notes about this PR can be found at https://bitcoincore.reviews/19160

[*] Note: the --enable-multiprocess feature is still experimental, and not enabled by default, and not yet supported on windows. More information can be found in doc/multiprocess.md

@DrahtBot
Copy link
Contributor

DrahtBot commented Jun 4, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, 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.

@ryanofsky
Copy link
Contributor Author

ryanofsky commented Jun 5, 2020

Updated d38f790 -> 9956298 (pr/ipc-echo.1 -> pr/ipc-echo.2, compare) fixing missing include causing build failures https://travis-ci.org/github/bitcoin/bitcoin/jobs/694309633#L2311
Updated 9956298 -> 885f0d1 (pr/ipc-echo.2 -> pr/ipc-echo.3, compare) to fix missing include error https://travis-ci.org/github/bitcoin/bitcoin/jobs/694434815#L2574
Rebased 885f0d1 -> 5219272 (pr/ipc-echo.3 -> pr/ipc-echo.4, compare) due to conflict with #19176 and reducing Init class dependencies

@promag
Copy link
Contributor

promag commented Apr 6, 2021

Thanks for reviewing!

Tested ACK 1290ccf on bionic. I'm having issues building on macOS but probably something is bad on my system, I'll check later.

I'd definitely encourage you to post an issue with any details to https://github.com/chaincodelabs/libmultiprocess/issues/new. Even if the issue isn't strictly related to libmultiprocess library, or even if it's not really a bug, all posts are welcome there and it's a good place to discuss problems and possible improvements without getting lost in PR review discussion here.

Submitted chaincodelabs/libmultiprocess#52

I wonder if is it possible to debug on the spawned processes so that b echoipc would work?

It can be awkward to try to attach to a short lived process with GDB. If you just want to set one breakpoint like that, that the easiest way may be to use the follow-fork-mode child GDB option. In other circumstances, I've been using the following patch to debug with GDB : ryanofsky@30f5c5a. This lets you set a STOP=node or STOP=wallet environment variable that newly spawned bitcoin-node or bitcoin-wallet processes will look for, and if they detect it, they will halt themselves on startup and print gdb command lines that can be used to attach to these processes and manually resume them.

Right, both approaches are suggested by looking around. I think it might make sense to include ryanofsky@30f5c5a or similar in a follow up and relevant instructions.

@dongcarl
Copy link
Contributor

dongcarl commented Apr 16, 2021

re-ACK 1290ccf

Reviewed git range-diff origin/master 6a2951a7c7690e4f974fb938e1434ca836762207 1290ccf8c70f5f11148683c3f69044fac9956e05 and it was mostly comment changes.

Question that has no bearing on merge-ability: why was #include <memory> added to src/interfaces/echo.cpp when it is already included in src/interfaces/echo.h?

@ryanofsky
Copy link
Contributor Author

Thanks for rechecking!

Question that has no bearing on merge-ability: why was #include <memory> added to src/interfaces/echo.cpp when it is already included in src/interfaces/echo.h?

Just preference, I guess. If you want to read a treatise on includes see https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/WhyIWYU.md. But I think if you use something in a file, you should include it or forward declare it, and more complicated rules are counterproductive.

@laanwj
Copy link
Member

laanwj commented Apr 22, 2021

Looks like there has been a silent merge conflict, unfortunately, while building locally i get the following error:

…/bitcoin/src/rpc/misc.cpp:662:47: error: use of undeclared identifier 'EnsureNodeContext'; did you mean 'EnsureAnyNodeContext'?
            if (interfaces::Ipc* ipc = Assert(EnsureNodeContext(request.context).init)->ipc()) {
                                              ^~~~~~~~~~~~~~~~~
                                              EnsureAnyNodeContext

EnsureNodeContext was removed in 038854f (#21391)

Fix "Disable GCC suggest-override warnings for proxy clients" chaincodelabs/libmultiprocess#40 is needed to prevent cirrus GCC failure https://cirrus-ci.com/task/6000489311502336?command=ci#L4294

This also includes other recent changes

chaincodelabs/libmultiprocess#35 Fix README.md markdown
chaincodelabs/libmultiprocess#37 Add "make check" target to build and run tests
chaincodelabs/libmultiprocess#38 Add "extends" inherited method support
chaincodelabs/libmultiprocess#41 Avoid depending on argument default constructors
chaincodelabs/libmultiprocess#42 Support attaching custom cleanup functions to proxy client and server classes
chaincodelabs/libmultiprocess#43 Drop hardcoded #include lines in generated files
Add bitcoin-node startup code to let it spawn and be spawned by other
processes
Add simple interfaces::Echo IPC interface with one method that just takes and
returns a string, to test multiprocess framework and provide an example of how
it can be used to spawn and call between processes.
@ryanofsky
Copy link
Contributor Author

#19160 (comment)

Looks like there has been a silent merge conflict

Thanks! Rebased and updated the call site.


Rebased 1290ccf -> 84934bf (pr/ipc-echo.30 -> pr/ipc-echo.31, compare) due to reported conflict with #21391

@fjahr
Copy link
Contributor

fjahr commented Apr 24, 2021

re-ACK 84934bf

Checked range-diff that only changes since last review were rebasing and fixing the silent merge conflict. Also built and ran tests locally and tested echo RPC manually.

Copy link
Contributor

@ariard ariard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 84934bf. Changes since last ACK fixes the silent merge conflict about EnsureAnyNodeContext(). Rebuilt and checked again debug command echoipc.

@laanwj laanwj merged commit ac219dc into bitcoin:master Apr 27, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Apr 27, 2021
ryanofsky added a commit to ryanofsky/libmultiprocess that referenced this pull request Jul 20, 2021
fanquake added a commit to fanquake/bitcoin that referenced this pull request Feb 18, 2022
Looks like this hasn't been needed since
chaincodelabs/libmultiprocess#25 and was just
missed in bitcoin#19160.
maflcko pushed a commit that referenced this pull request Feb 19, 2022
07dcf1a build: remove boost dep from libmultiprocess (fanquake)

Pull request description:

  Looks like this hasn't been needed since chaincodelabs/libmultiprocess#25 and was just missed in #19160.

ACKs for top commit:
  ryanofsky:
    Code review ACK 07dcf1a. Should probably wait for GUIX build results, but I think this should be fine
  hebasto:
    ACK 07dcf1a

Tree-SHA512: 7988efd4aaf6ad512d60cfd33f350df56090daf88aac3aed2a1d400e80bc723dc27d27f5fa5d75359f9fae60d04b87d4b120d4e79e3079df8631956ab6c3b83c
hmel pushed a commit to hmel/bitcoin that referenced this pull request Feb 20, 2022
Looks like this hasn't been needed since
chaincodelabs/libmultiprocess#25 and was just
missed in bitcoin#19160.
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request May 25, 2022
…rectory

Error was reported by SatoriHoshiAiko in
bitcoin#25207 and happens unpredictably
because make doesn't always build dependencies in the same order.

The source file src/ipc/capnp/protocol.cpp includes some generated headers so
needs to have an explicit dependency specified in the makefile so the headers
will be generated before the file is compiled. bitcoin#19160 added the explicit
dependency, but it was incorrect because it referred to an old file path from
before the source file was renamed (ipc.cpp -> protocol.cpp)
ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request May 25, 2022
…tory

Error was reported by SatoriHoshiAiko in
bitcoin#25207 and happens unpredictably
because make doesn't always build dependencies in the same order.

The source file src/ipc/capnp/protocol.cpp includes some generated headers so
needs to have an explicit dependency specified in the makefile so the headers
will be generated before the file is compiled. bitcoin#19160 added the explicit
dependency, but it was incorrect because it referred to an old file path from
before the source file was renamed (ipc.cpp -> protocol.cpp)
fanquake added a commit that referenced this pull request May 27, 2022
… file or directory

44904aa multiprocess build cleanup: comment on manual dependencies (Ryan Ofsky)
6e1c16c multiprocess build fix: ipc/capnp/init.capnp.h: No such file or directory (Ryan Ofsky)

Pull request description:

  Error was reported by SatoriHoshiAiko in #25207 and happens unpredictably because make doesn't always build dependencies in the same order.

  The source file `src/ipc/capnp/protocol.cpp` includes some generated headers so needs to have an explicit dependency specified in the makefile so the headers will be generated before the file is compiled. #19160 added the explicit dependency, but it was incorrect because it referred to an old file path from before the source file was renamed (`ipc.cpp` -> `protocol.cpp`)

ACKs for top commit:
  hebasto:
    re-ACK 44904aa

Tree-SHA512: 578ef4ef35a97e9d8d4e6d4edf39e57a32674234bf145e8159268324cb6ba15b420517afc07f6f42bb11a562954ea74af686c3fb92ce178c1fc378421b352531
gwillen pushed a commit to ElementsProject/elements that referenced this pull request Jun 1, 2022
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
Comment on lines +258 to +262
int exit_status;
std::unique_ptr<interfaces::Init> init = interfaces::MakeNodeInit(node, argc, argv, exit_status);
if (!init) {
return exit_status;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize for revisiting this old PR, but I couldn't resist asking to clarify things for me.

As far as I understand, interfaces::MakeNodeInit returns a std::unique_ptr that owns an instance of init::BitcoindInit or throws an exception. Given this understanding, it seems unclear how the return exit_status; statement could ever execute.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, interfaces::MakeNodeInit returns a std::unique_ptr that owns an instance of init::BitcoindInit or throws an exception. Given this understanding, it seems unclear how the return exit_status; statement could ever execute.

There are two interfaces:MakeNodeInit functions. The one in src/init/bitcoind.cpp which is linked into bitcoind will leave exit_status unchanged, as you say. The one in src/init/bitcoin-node.cpp which is linked into bitcoin-node will set the exit status if there is an IPC error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Thank you.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
Development

Successfully merging this pull request may close these issues.