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

[experimental] Multiprocess bitcoin #10102

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open

Conversation

@ryanofsky
Copy link
Contributor

@ryanofsky ryanofsky commented Mar 27, 2017

This PR is part of the process separation project.


This is based on bitcoin-core/gui#360 + #22215 + #22217 + #22218 + #22219. The non-base commits are:


This PR adds an --enable-multiprocess configure option which builds new bitcoin-node, bitcoin-wallet, and bitcoin-gui executables with relevant functionality isolated into different processes. See doc/multiprocess.md for usage details and future plans.

The change is implemented by adding a new Init interface that spawns new wallet and node subprocesses that can be controlled over a socketpair by calling Node, Wallet, and ChainClient methods. When running with split processes, you can see the IPC messages going back and forth in -debug=1 output. A followup PR will add -ipcbind and -ipcconnect options that allow more flexibility in how processes are connected.

The IPC protocol used is Cap'n Proto, but this could be swapped out for another protocol. Cap'n Proto types and libraries are only accessed in the src/interfaces/capnp/ directory, and not in any public headers or other parts of bitcoin code.


Slides from a presentation describing this change are available on google drive. Demo code used in the presentation was from an older version this PR (tag ipc.21, commits).

@jonasschnelli
Copy link
Member

@jonasschnelli jonasschnelli commented Mar 28, 2017

Oh. Nice.
I expected much more code to achieve this.

Conceptually I think this goes into the right direction, though, I'm not sure if this could end up being only a temporary in-between step that may end up being replaced.
Because, it may be more effective to split the Qt/d part completely and let them communicate over the p2p protocol (SPV and eventually RPC). More effective because it would also allow to run Qt independent from a trusted full node (if not trusted, use mechanism like full block SPV, etc.).

Though, I'm aware that capnp has an RPC layer. But this would introduce another API (RPC / ZMQ / REST and then capnp RPC).

I'm not saying this is the wrong direction, but we should be careful about adding another API.

Three questions:

  • Would the performance be impractical if we would try to use the existing RPC API?
  • Could the capnp approach (or lets say IPC approach) be designed as a (or the) new API ("JSON RPC v2" and replacement for ZMQ)?
  • Does capnp provide a basic form of authentication? Would that even be required?
@ryanofsky
Copy link
Contributor Author

@ryanofsky ryanofsky commented Mar 28, 2017

Would the performance be impractical if we would try to use the existing RPC API?

Reason this is currently using capnp is not performance but convenience. Capnp provides a high level API that supports bidirectional, synchronous, and asynchronous calls out of the box and allows me to easily explore implementation choices in bitcoin-qt without having to worry about low level protocol details, write a lot of parameter packing/unpacking boilerplate, and implement things like long polling.

Capnp could definitely be replaced by JSON-RPC, though, and I've gone out of my way to support this by not calling capnp functions or using capnp types or headers anywhere except the ipc/server.cpp and ipc/client.cpp files. No code outside of these two files has to change in order to move to a different protocol.

Could the capnp approach (or lets say IPC approach) be designed as a (or the) new API ("JSON RPC v2" and replacement for ZMQ)?

It could, but I'm going out of my way right now specifically NOT to add yet another bitcoind public API that could add to the JSON-RPC/REST/ZMQ/-blocknotify/-walletnotify confusion. The IPC here doesn't happen over a TCP port or even a unix socket path but over an anonymous socketpair using an inherited file descriptor. (I haven't done a windows implementation yet but similar things are possible there).

I'm trying to make the change completely internal for now and transparent to users. Bitcoin-qt should still be invoked the same way and behave the same way as before, starting its own node and wallet. It just will happen to do this internally now by forking a bitcoind executable rather than calling in-process functions.

This change will not add any new command line or GUI options allowing bitcoin-qt to connect to bitcoinds other than the one it spawns internally. Adding these features and supporting new public APIs might be things we want to do in the future, but they would involve downsides and complications that I'm trying to avoid here.

Does capnp provide a basic form of authentication? Would that even be required?

It's not required here because this change doesn't expose any new socket or endpoint, but it could be supported. Capnp's security model is based on capabilities, so to add authentication, you would just define a factory function that takes credentials as parameters and returns a reference to an object exposing the appropriate functionality.

@gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Mar 28, 2017

I'm really uncomfortable with using capn proto, but fine enough for some example testing stuff!

I'm a fan of this general approach (ignoring the use of capn proto) and I think we should have done something like it a long time ago.

@dcousens
Copy link
Contributor

@dcousens dcousens commented Mar 28, 2017

strong concept ACK, but if is feasible, would prefer usage of the existing RPC instead of capn'proto

@laanwj
Copy link
Member

@laanwj laanwj commented Mar 29, 2017

Concept ACK, nice.

I'm really uncomfortable with using capn proto, but fine enough for some example testing stuff!

Please, let's not turn this into a discussion of serialization and RPC frameworks. To be honest that's been one of the things that's putting me off of doing work like this. If you want to suggest what framework to use, please make a thorough investigation of what method would be best to use for our specific use case, and propose that, but let's not start throwing random "I'm not comfortable with X" comments.

We already use google protocol buffers in the GUI for payment requests to in a way that would be the straightforward choice. I'm also happy you didn't choose some XML-based abomonation or ASN.1. But anyhow, not here. For this pull it's fine to use whatever RPC mechanism you're comfortable with.

This change will not add any new command line or GUI options allowing bitcoin-qt to connect to bitcoinds other than the one it spawns internally.

I'm also perfectly fine with keeping the scope here to "communication between GUI and bitcoind". This is not the place for introducing another external interface. Might be an option at some point in the future, but for now process isolation is enough motivation.

}

bool WalletModel::getDefaultWalletRbf() const
{
return fWalletRbf;

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

Yep I guess most of these calls should be turned into async calls and not wait on a response synchronously blocking the GUI. Not necessarily in the first iteration of this, of course.

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

Yep I guess most of these calls should be turned into async calls and not wait on a response synchronously blocking the GUI. Not necessarily in the first iteration of this, of course.

Another alternative in some of these cases is to consolidate many low level calls into fewer calls of a higher level interface.

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

I think that's not optional but a required element of making this asynchronous, otherwise there'd be a lot of roundtrips.

Edit: Though ofcourse one of the things cap'n'proto advertises with is that there is 'zero roundtrip overhead', because of the promise pipelining, but we don't want to depend too strongly on that.

}

interface Wallet {
getBalance @0 () -> (value :Int64);

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

Pretty nice. So the IPC endpoint exposes multiple "objects". It can also expose multiple instances of one class? (e.g. for multiwallet?).

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

It can also expose multiple instances of one class?

Yes, the ipc::Node::wallet() method right now returns an ipc::Wallet interface wrapping pwalletMain, but it could support multiwallet by just adding an argument that indicates a different wallet object to return.

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

Cool. I like this auto-generated IPC stuff. Saves writing a lot of boilerplate.

close(fd);
}
}
if (execlp(BITCOIN_DAEMON_NAME, BITCOIN_DAEMON_NAME, "-ipcfd", std::to_string(fds[0]).c_str(), nullptr) != 0) {

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

Should it pass through parameters? Most of the parameters to bitcoin-qt will actually be for the daemon. Or will you provide parameters in a later stage through IPC?

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

Should it pass through parameters? Most of the parameters to bitcoin-qt will actually be for the daemon. Or will you provide parameters in a later stage through IPC?

The change I'm working on now (not yet pushed) provides the parameters over IPC. It adds an ipc::Node::parseParameters method in client.h which calls ParseParameters() in bitcoind.

+    //! Set command line arguments.
+    void parseParameters(int argc, const char* const argv[]) const;
+
     //! Get help message string.
     std::string helpMessage(HelpMessageMode mode) const;
 
+    //! Start node.
+    bool appInit() const;
+
+    //! Stop node.
+    void appShutdown() const;
+
+    //! Return whether shutdown was requested.
+    bool shutdownRequested() const;

ParseParameters() is also called on the bitcoin-qt side in current change. This gets the job done, but could be improved later, since really the bitcoind global variables set by ParseParameters() should not even be linked into bitcoin-qt.

This comment has been minimized.

@laanwj

laanwj Mar 31, 2017
Member

Right, ideally bitcoin-qt would need only a very small subset of the bitcoind code.

@@ -298,9 +303,9 @@ void BitcoinCore::shutdown()
try
{
qDebug() << __func__ << ": Running Shutdown in thread";
Interrupt(threadGroup);
FIXME_IMPLEMENT_IPC(Interrupt(threadGroup));
threadGroup.join_all();

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

The thread group is completely remote in the case of IPC, isn't it? I guess this entire function should be done differently when IPC is used. E.g. send a shutdown command to the core, then have the shutdownResult event come from remote as response when done.

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

The thread group is completely remote in the case of IPC, isn't it?

Yes the change I'm working on now adds threadGroup and scheduler members to NodeServer in ipc/server.cpp, removing the current instances in BitcoinCore.

@@ -676,7 +682,7 @@ int main(int argc, char *argv[])
app.createOptionsModel(IsArgSet("-resetguisettings"));

// Subscribe to global signals from core
uiInterface.InitMessage.connect(InitMessage);
FIXME_IMPLEMENT_IPC_VALUE(uiInterface).InitMessage.connect(InitMessage);

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

How would you handle uiInterface in this model, e.g. signals from the server to the client?

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

How would you handle uiInterface in this model, e.g. signals from the server to the client?

This line needs to change to ipcNode.handleInitMessage(InitMessage). If you look at the ipc::Node::handleInitMessage implementation, it takes a std::function argument, creates a capnp InitMessageCallback::Server object that can invoke it, and sends a reference to that object over the IPC channel to bitcoind. bitcoind then calls uiInterface.InitMessage.connect with a handler that sends messages with the InitMessageCallback object.

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

So the server then effectively calls an object on the client when the notification happens? No polling/waiting involved? That's great.

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

So the server then effectively calls an object on the client when the notification happens? No polling/waiting involved? That's great.

Yes, though to be clear, there is still polling/waiting happening under the hood. It just gets handled by the capnp event loop, which waits for incoming IPC messages and dispatches to InitMessageCallback::Server::call and other server methods. The change I'm working on now (not yet pushed) spawns a new thread in ipc/client.cpp to run the event loop.

This comment has been minimized.

@laanwj

laanwj Mar 31, 2017
Member

Yes, I understand that, but one of the problems with existing proposals for using RPC to communicate to the server had no way to handle asynchonous notifications, so needed to e.g. poll for new transactions every few seconds. This protocol clearly does support true bidirectional communication.

As for the capnp event loop, as most of the responses and notifications from the server involve updating the UI, couldn't we integrate that into Qt's event loop? Conceptually that'd be easier. Qt only allows GUI updates from a single thread, so if the capnp event loop is separete, everything will have to be separately ferried through Qt's signal mechanism to get to the GUI thread.

This comment has been minimized.

@ryanofsky

ryanofsky Apr 6, 2017
Author Contributor

As for the capnp event loop, as most of the responses and notifications from the server involve updating the UI, couldn't we integrate that into Qt's event loop?

It should be possible to integrate the qt and capnp event loops (http://stackoverflow.com/questions/33131595/what-is-a-good-way-to-integrate-3rd-party-asynchronous-apis-with-capn-proto-rpc), but for now StartClient is just spawning an event loop thread, since this seems like the path of least resistance.

return false;
return true;
}

bool WalletModel::abandonTransaction(uint256 hash) const
{
LOCK2(cs_main, wallet->cs_wallet);
return wallet->AbandonTransaction(hash);
LOCK2(FIXME_IMPLEMENT_IPC_VALUE(cs_main), wallet->cs_wallet);

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

This locking (either of cs_main or wallet->cs_wallet) makes no sense when a remote core is used.

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

This locking (either of cs_main or wallet->cs_wallet) makes no sense when a remote core is used.

Yeah, the point of the FIXME_IMPLEMENT_IPC macro is really just to segfault and indicate places in the code which need to be updated to support IPC. Many of them are pretty nonsensical.


bool StartServer(int argc, char* argv[], int& exitStatus)
{
if (argc != 3 || strcmp(argv[1], "-ipcfd") != 0) {

This comment has been minimized.

@laanwj

laanwj Mar 29, 2017
Member

FYI this is quite similar to how fd handles are passed in for the P2P and RPC port in my cloudabi port: https://github.com/laanwj/bitcoin/blob/2017_03_cabi_fs/src/httpserver.cpp#L357 https://github.com/laanwj/bitcoin/blob/2017_03_cabi_fs/src/init.cpp#L1356

It's a bit of a shame that argument parsing doesn't work here yet so this needs to use manual parsing using C functions :/

This comment has been minimized.

@ryanofsky

ryanofsky Mar 29, 2017
Author Contributor

It's a bit of a shame that argument parsing doesn't work here yet so this needs to use manual parsing using C functions :/

I think I could change this to at least use GetArg like you are doing in your cloudabi code.

@ryanofsky ryanofsky force-pushed the ryanofsky:pr/ipc branch from bf5f8ed to 0ca73bc Apr 6, 2017
Copy link
Contributor Author

@ryanofsky ryanofsky left a comment

Updated and rebased bf5f8ed -> 0ca73bc (pr/ipc.0 -> pr/ipc.1)

There's a lot of new changes here. More functions and callbacks have been wrapped, and there's now support for asynchronous calls that don't block event threads in the client and server.

At this point it would be very helpful to have code review for the main commit (0ca73bc "Add barebones IPC framework to bitcoin-qt and bitcoind"), because all the real infrastructure is now in place, and the main thing left to do is wrap up more functions and callbacks in IPC calls so the GUI can be functional.

@@ -676,7 +682,7 @@ int main(int argc, char *argv[])
app.createOptionsModel(IsArgSet("-resetguisettings"));

// Subscribe to global signals from core
uiInterface.InitMessage.connect(InitMessage);
FIXME_IMPLEMENT_IPC_VALUE(uiInterface).InitMessage.connect(InitMessage);

This comment has been minimized.

@ryanofsky

ryanofsky Apr 6, 2017
Author Contributor

As for the capnp event loop, as most of the responses and notifications from the server involve updating the UI, couldn't we integrate that into Qt's event loop?

It should be possible to integrate the qt and capnp event loops (http://stackoverflow.com/questions/33131595/what-is-a-good-way-to-integrate-3rd-party-asynchronous-apis-with-capn-proto-rpc), but for now StartClient is just spawning an event loop thread, since this seems like the path of least resistance.

@ryanofsky ryanofsky force-pushed the ryanofsky:pr/ipc branch from 0ca73bc to 1ea8987 Apr 7, 2017
@ryanofsky
Copy link
Contributor Author

@ryanofsky ryanofsky commented Apr 7, 2017

Updated and rebased 0ca73bc -> 5e28c2f (pr/ipc.1 -> pr/ipc.3) to avoid a conflict. Main addition is an expanded src/ipc/README.md file.

Again it would be very helpful to have some code review for the main commit (5e28c2f "Add barebones IPC framework to bitcoin-qt and bitcoind"). Giving feedback on the README file would be an easy place to start.

@ryanofsky ryanofsky force-pushed the ryanofsky:pr/ipc branch 2 times, most recently from 5e28c2f to dda3756 Apr 10, 2017
@ryanofsky
Copy link
Contributor Author

@ryanofsky ryanofsky commented Apr 10, 2017

Updated 5e28c2f -> dda3756 (pr/ipc.3 -> pr/ipc.4)

This implements two suggestions from @JeremyRubin:

  • It includes a small commit demonstrating what it looks like to add a single new method to the API:
    dda3756 Add ipc::Node::getNodeCount method. This should help give a clearer picture of the layers involved in implementing an IPC call.

  • Instead of adding Cap'n Proto code and modifying Qt code in a single commit, it includes a new early commit (1407a2b Add ipc::Node and ipc::Wallet interfaces that introduces new src/ipc/interfaces.h and src/ipc/interfaces.cpp files and ports Qt code to use them without any Cap'n Proto stuff. This shows the separation between Qt updates and IPC implementation details better and makes it easier to see how a different IPC system could be substituted in for Cap'n Proto. This commit could even be made into a separate PR.

@ryanofsky
Copy link
Contributor Author

@ryanofsky ryanofsky commented Apr 14, 2017

@laanwj pointed out in IRC (https://botbot.me/freenode/bitcoin-core-dev/msg/83983170/) that this change could help make the GUI more responsive by preventing Qt event processing from getting blocked, which currently happens in the monolithic bitcoin-qt when the main GUI thread makes a call to a slow libbitcoin function, or waits a long time for a cs_main or cs_wallet lock.

At the time in IRC, I didn't think this change could directly help gui responsiveness, because although it does move libbitcoin and LOCK calls out of the bitcoin-qt process and into the bitcoind process, it just replaces these calls with blocking IPCs that make the GUI equally unresponsive when they tie up the main GUI thread.

However, this doesn't have to be the case. The place where IPC calls currently block waiting for responses is the return promise.get_future().get(); line in ipc::util::Call::send method here: https://github.com/ryanofsky/bitcoin/blob/pr/ipc.4/src/ipc/util.h#L166

But the std::promise object used in that line could easily be replaced with a Qt-aware promise object that processes GUI events while the promise is blocked. (The Qt-aware promise implementation would check if it is being used on the main GUI thread, and if so use a local Qt event loop substituting
loop.exec() for std::future::get() and loop.quit() for std::promise::set_value().)

This would add more overhead and make the average IPC call a little slower. But it would avoid situations where an unexpectedly slow IPC call ties up the whole gui, so it might be worth doing anyway.

@laanwj
Copy link
Member

@laanwj laanwj commented Apr 14, 2017

@ryanofsky Yes, integrating the IPC event loop and Qt event loop would help responsiveness.
Though I remember there were some issues in some cases with recursively calling into the Qt event loop (e.g. things need to be reentrant, deleteLater stuff runs earlier than expected, to keep in mind).

@sipa
Copy link
Member

@sipa sipa commented Apr 17, 2017

@ryanofsky I'm not familiar with Qt or capnproto, but I don't understand what the move to a different process has to do with making things less blocking. Any changes in architecture that would result in less blocks should equally be possible within the same process.

@sipa
Copy link
Member

@sipa sipa commented Apr 17, 2017

This change will not add any new command line or GUI options allowing bitcoin-qt to connect to bitcoinds other than the one it spawns internally. Adding these features and supporting new public APIs might be things we want to do in the future, but they would involve downsides and complications that I'm trying to avoid here.

I don't understand the goal here. On itself, there seems little benefit in separating the GUI and the rest into separate processes if those two processes still depend on each other (this is different from separating the wallet from the node, for example, as there as security considerations there... but for that use case the easiest approach seems to just have a lightweight mode and running two instances).

I think it would be awesome if bitcoin-qt could be started and stopped independently to control a bitcoind process in the background, but if that's not the intent, what is the purpose?

@ryanofsky
Copy link
Contributor Author

@ryanofsky ryanofsky commented Apr 17, 2017

Any changes in architecture that would result in less blocks should equally be possible within the same process.

Let's say there are 50 places where bitcoin-qt calls a libbitcoin function. That means there are 50 places to update if you want bitcoin-qt handle to events while the function calls are executing. WIth the IPC framework, there is only one place you have to update instead of 50 places (if you want to do this).

On itself, there seems little benefit in separating the GUI and the rest into separate processes if those two processes still depend on each other.

Ok, so you think the benefits are small, and I think they are more significant.

I think it would be awesome if bitcoin-qt could be started and stopped independently to control a bitcoind process in the background,

This is trivial once bitcoin-qt is controlling bitcoind across a socket. I'm just implementing the socket part first, without introducing new UI features for now.

@sipa
Copy link
Member

@sipa sipa commented Apr 17, 2017

I think it would be awesome if bitcoin-qt could be started and stopped independently to control a bitcoind process in the background,

This is trivial once bitcoin-qt is controlling bitcoind across a socket. I'm just implementing the socket part first, without introducing new UI features for now.

Ok, that's what I was missing. It wasn't clear to me that this was a just first step towards a more useful separation.

ryanofsky added a commit to ryanofsky/bitcoin that referenced this pull request Apr 20, 2017
This doesn't crash currently because the method doesn't access any object
members, but this behavior is fragile and incompatible with bitcoin#10102.
@ryanofsky ryanofsky force-pushed the ryanofsky:pr/ipc branch from dda3756 to ab0afba Apr 20, 2017
ryanofsky added 18 commits Jul 1, 2021
interfaces::Chain is an abstract class and declaring the method const
would be exposing an internal implementation details to caller. Also,
more practically, the multiprocess implementation of
interfaces::Chain::isTaprootActive needs to be non-const for IPC to
work.
Add interfaces::ExternalSigner to allow signer objects to be referenced
and controlled in different processes. Always run external signer code
in bitcoin-wallet process, not bitcoin-gui or bitcoin-node processes.
Needed because BlockConnected notifications are a lot slower with the wallet
running in separate process.
Add separate init implementations instead of sharing existing bitcoind
and bitcoin-node ones, so they can start to be differentiated in
upcoming commits with node and wallet code no longer linked into the the
bitcoin-gui binary and wallet code no longer linked into the
bitcoin-node binary.
Spawn node subprocess instead of running node code internally
Spawn wallet subprocess instead of running wallet code internally
@ryanofsky ryanofsky force-pushed the ryanofsky:pr/ipc branch from 24dd84a to 1326c4a Jul 1, 2021
ryanofsky referenced this pull request Jul 8, 2021
Spawn node subprocess instead of running node code internally
@ryanofsky ryanofsky force-pushed the ryanofsky:pr/ipc branch from 1326c4a to 3f2ca2a Jul 9, 2021
@ryanofsky
Copy link
Contributor Author

@ryanofsky ryanofsky commented Jul 9, 2021

Rebased 1326c4a -> 3f2ca2a (pr/ipc.156 -> pr/ipc.157, compare) on top of #22218 pr/ipc-ctx.2 with comment improvements that were discussed in #22218 (review) and 2516d39#commitcomment-53226160

// Extra initialization code that runs when a bitcoin-node process is
// spawned by a bitcoin-gui process, after the ArgsManager configuration
// is transferred from the parent process to the child process.
m_ipc->context().init_process = [this] {

This comment has been minimized.

@ryanofsky

ryanofsky Jul 12, 2021
Author Contributor

In commit "Make bitcoin-gui spawn a bitcoin-node process" (2516d39):

re: 2516d39#r53368428

IIUC, it's going to be call at the first invocation on the server from the client as it's dependent on the whole serverInvoke()/MakeServerField()/etc call chain ? Sometimes it's hard to follow which objects are defined in bitcoin, which ones are in libmultiprocess and which ones are dynamically generated by mpgen. Though i agree it's fine for now, we can improve with time.

init_process is bitcoin-specific and libmultiprocess can't access it or reference it, and it isn't related to IPC method invocation (serverInvoke is a libmultiprocess internal function that bitcoin code shouldn't access and doesn't reference which translates an incoming IPC method call from a remote process to a C++ method call on a local object.)

init_process is a hack to deal with the fact that bitcoin code uses a bunch of global variables that depend on the gArgs global variable and they need to be initialized at some point.

When bitcoin is running with wallet & node & gui code in the same process, global variables only have to be initialized once by existing init code. But if the node process spawns a wallet process, or if the GUI process spawns a node process, then there are multiple copies of the global variables in different processes, and they have to be newly initialized in each spawned process, and existing init code is no longer sufficient. That is why the GlobalArgs class and init_process callback are introduced. GlobalArgs transfers gArgs state from the parent process to the child process and init_process sets up logging and other global variables that depend on gArgs.

Ideally there would be no global variables shared between node wallet and GUI code (they would move into NodeContext and WalletContext objects) and the init_process hack could go away. Short of that, I maybe rename init_process or you could think of it as something like init_bitcoin_shared_global_variables_in_newly_spawned_child_process_after_transferring_gargs

@DrahtBot
Copy link
Contributor

@DrahtBot DrahtBot commented Jul 14, 2021

🐙 This pull request conflicts with the target branch and needs rebase.

Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft".

MarcoFalke added a commit to MarcoFalke/bitcoin-core that referenced this pull request Jul 22, 2021
…ontext structs

3e33d17 Add ipc::Context and ipc::capnp::Context structs (Russell Yanofsky)

Pull request description:

  These are currently empty structs but they will be used to pass some function and object pointers from bitcoin application code to IPC hooks that run, for example, when a remote object is created or destroyed, or a new process is created.

  ---

  This PR is part of the [process separation project](https://github.com/bitcoin/bitcoin/projects/10). The commit was first part of larger PR bitcoin#10102.

ACKs for top commit:
  ariard:
    Code Review ACK 3e33d17

Tree-SHA512: fd949fae5f1a973d39cb97f2745821ab2f62b98e166e53bc2801f97dcde988e18faaaaa0ffc2a82c170938b3a18078b6162fa35460e6e7c635e681b3c9e5b0a6
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Process Separation
  
In progress
Linked issues

Successfully merging this pull request may close these issues.

None yet