-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Clean up mapArgs and mapMultiArgs Usage #9243
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
extern std::map<std::string, std::string> mapArgs; | ||
extern std::map<std::string, std::vector<std::string> > mapMultiArgs; | ||
extern std::map<std::string, std::vector<std::string> > _mapMultiArgs; | ||
static const std::map<std::string, std::vector<std::string> >& mapMultiArgs = _mapMultiArgs; |
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 believe this instantiates a mapMultiArgs
variable into every .cpp file (all initialized as the same reference).
This will work, I think:
util.cpp:
map<string, vector<string> > _mapMultiArgs;
+static std::map<std::string, std::vector<std::string> > mapMultiArgs_;
+const std::map<std::string, std::vector<std::string> >& mapMultiArgs = mapMultiArgs;
bool fDebug = false;
util.h:
-extern std::map<std::string, std::vector<std::string> > _mapMultiArgs;
-static const std::map<std::string, std::vector<std::string> >& mapMultiArgs = _mapMultiArgs;
+extern const std::map<std::string, std::vector<std::string> >& mapMultiArgs;
extern bool fDebug;
e9489e7
to
69337dc
Compare
Concept ACK. |
Nice. |
utACK 69337dcab02e2e972711781ae1fba7f541d67b17, but needs rebase. Also, maybe the "Fix calculation of number of bound sockets to use" commit should be moved to a separate PR; maybe we want to backport it? |
69337dc
to
14e3df2
Compare
Rebased and opened #9253, which this is now dependant on (the socket count fix). |
utACK 14e3df2 |
This seems incompatible with #8994 , if there's any suggestions there, specifically regarding 5cc59df0dce56c9393b2bd1af773d708bb76a3cb (aka "Globals: Allow to parse arguments without implicitly using the argMap globa"l), that would be welcomed. |
int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1); | ||
int nBind = std::max( | ||
(mapMultiArgs.count("-bind") ? mapMultiArgs.at("-bind").size() : 0) + | ||
(mapMultiArgs.count("-whitebind") ? mapMultiArgs.at("-whitebind").size() : 0), size_t(1)); |
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.
github-web-view-Nit: Needs this patch removed after c1a5227
(I think you can push an empty commit and then remove it by force push, to get this removed from the web view)
utACK 14e3df21e067f41b6f624ea7ee25601f87267faa |
@jtimon I think for things which are their own classes, they should either have the arguments they care about passed into the constructor, or passed in when they need them (eg the way mempool limiting is done now). The concept of a map from arguments to values is inherintly Bitcoin Core-specific, so inherintly global. |
I think it is better to discuss the different options for Chainparams in #8994 (I've been trying to do something similar for the never created policy class for very long too), I will answer to this there.
Huh? Anything that is specific to Bitcoin Core is "inherently global"? |
By "inherently global", I mean that eg mapArgs probably should not exist in anything like libbitcoinconsensus, and, generally, can just be a global that is queries when things are initialized and then the parameters fed into the object which cares about them. |
Right, I agree it should not exist in libbitcoinconsensus. If mapArgs and mapMultiArgs are initialized once and afterwards only accessed as const (perhaps similarly to what chainparams.o is doing with InitParams and const CChainParams& Params() or what is being done in 31f576b ), I don't see how could there be any concurrency issues or why a new lock would be needed. I also don't understand why this PR isn't consistent in its treatment of mapArgs and mapMultiArgs (one is hidden, the other can be accessed as const). Although I like many of the changes in this PR, until I understand some of the decisions, concept NACK. |
The contents of e87822043d4118d1b02d066ee213d341af3ff4e9 are less about passing around a map (which is, itself, kinda insane) and more about cleaning up the insane argument-parsing monstrosity in the zmq stuff. As for generally, I dont get your crusade against globals. Some things, like arguments, simply /are/ globals. In places where we want isolated chunks for testing, those isolated chunks shouldn't be given a list of all arguments passed to the program, they should be given the arguments that they care about. Note that mapArgs stuff isnt exclusively accessed in a clean order...theres a bunch of Qt initialization that I dont know when its called (and I believe there is some incorrect behavior in init as well), nor do I care - adding a lock has almost 0 overhead (we're already inexing into a map anyway) when there is no contention and its much more obviously correct and harder to fuck up in the future. As for mapArgs/mapMultiArgs - I could add accessors to mapMultiArgs, but it has to return the vector of arguments anyway, so I see little point. Feel free to clean it up in a separate PR. |
I don't see how using something implicitly is any more sane than passing it explicitly.
No, global variables are never strictly necessary, they are always a design choice (which doesn't mean is always a bad choice, but it usually is in my experience).
If you want to test the old CZMQNotificationInterface::Create(&args) you can create your own map and only setting the values that it cares about. If you want to impede it from using other args that it should not care about, you are not achieving that with the hidden global accessible from everywhere.
Ok, that's a good reason to use the lock, at least as a short term clean solution. I was forgetting qt setting args after initialization, thanks. Concept ACK. |
The problem with the ZMQ stuff is less that its being passed the list of all arguments in the world, and more that it bends over backwards to use map operations to look up 4 elements... Note that this PR isnt about creating an "ideal design" it is about fixing actual race conditions (ok, admittedly that arent a big deal) in mapArgs accessing as used in the codebase today. Eventually mapArgs will only exist in init.cpp and the relevant args passed around to different submodules as neccessary, but for now, this makes it obviously safe. |
re zmq: I understand you considered two different "problems":
I'm very sorry for overreacting by misinterpreting this as an "ideal design" without joining what I understand as an ongoing discussion. For example, @MarcoFalke seems to be ok with passing the argsMap explicitly where we can, as long as the 2 maps were hidden behind a class first, which I wasn't very fond of at first, but I think makes sense. Also, somewhere in #5595 had an idea for making a dynamic qt form for configuring policy from an argMap and something like my std::vector<std::pair<std::string, std::string> > CDefaultPolicy::GetOptionsHelp() (something like in https://github.com/bitcoin/bitcoin/pull/7820/files#diff-d22bc3e058f8982972e2eb381a1df668R261 but with a single thing looks ridiculous). I loved that idea, and thought it was extensible for other things (and I'm all fine with these new options requiring restart). Anyway, as said, I'm happy to keep discussing this but this is not the place and I already disrupted the thread of this PR enough.
Just as globals, "known" race conditions make reasoning about how the system works harder.
I agree that in many cases this is what makes the most sense, but we shouldn't disregard "shortcuts" like Consensus::Params, chainparams, policy...(again, probably not to discuss in this PR, I'm making too much noise in this PR already). |
Needs rebase. |
14e3df2
to
62b8ba5
Compare
Rebased. @jtimon I suppose we dont really strongly disagree on the goal, though maybe disagree on how to get there. Can we leave that for another PR and take this as-is to fix the issues that we have now? |
ACK. |
ACK on wrapping the accesses. I'm surprised that a lock is needed here, I assumed the arguments were read-only after initialization. Anyhow there shouldn't be any argument accesses in an inner loop where overhead matters so adding the lock just in case makes sense, I guess.
Yes the ZMQ argument parsing loop is silly. I fixed that once, as part of the mempool notifications, but it never got merged. |
reACK 62b8ba5f0a3d22e0dfcef9a3e1e7fa5c3f48b5ce |
0c77f37
to
040a43f
Compare
I would have been happy with just renaming the commit message, or explaining further what garbage were you cleaning, but thanks. No opposition on removing getArg from the loop, but you maintained the loop and everything which was supposedly wrong with it (except from passing mapArgs as arguments, which is the art you wanted to remove I think). |
040a43f
to
c2f61be
Compare
Fixed @dcousens' comments from #9419 (comment) |
utACK c2f61be, and thanks for linking me @TheBlueMatt |
utACK c2f61be |
c2f61be Add a ForceSetArg method for testing (Matt Corallo) 4e04814 Lock mapArgs/mapMultiArgs access in util (Matt Corallo) 4cd373a Un-expose mapArgs from utils.h (Matt Corallo) 71fde55 Get rid of mapArgs direct access in ZMQ construction (Matt Corallo) 0cf86a6 Introduce (and use) an IsArgSet accessor method (Matt Corallo) 2b5f085 Fix non-const mapMultiArgs[] access after init. (Matt Corallo) c8042a4 Remove arguments to ParseConfigFile (Matt Corallo)
Thank you, this will hirt less the faster it is imo.
…On 27 Dec 2016 19:17, "Pieter Wuille" ***@***.***> wrote:
Merged #9243 <#9243>.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#9243 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AA9jSu-ji0J3ZdPwz4-8SGdcbYpBK71Lks5rMVZVgaJpZM4K_wjb>
.
|
c2f61be Add a ForceSetArg method for testing (Matt Corallo) 4e04814 Lock mapArgs/mapMultiArgs access in util (Matt Corallo) 4cd373a Un-expose mapArgs from utils.h (Matt Corallo) 71fde55 Get rid of mapArgs direct access in ZMQ construction (Matt Corallo) 0cf86a6 Introduce (and use) an IsArgSet accessor method (Matt Corallo) 2b5f085 Fix non-const mapMultiArgs[] access after init. (Matt Corallo) c8042a4 Remove arguments to ParseConfigFile (Matt Corallo)
c2f61be Add a ForceSetArg method for testing (Matt Corallo) 4e04814 Lock mapArgs/mapMultiArgs access in util (Matt Corallo) 4cd373a Un-expose mapArgs from utils.h (Matt Corallo) 71fde55 Get rid of mapArgs direct access in ZMQ construction (Matt Corallo) 0cf86a6 Introduce (and use) an IsArgSet accessor method (Matt Corallo) 2b5f085 Fix non-const mapMultiArgs[] access after init. (Matt Corallo) c8042a4 Remove arguments to ParseConfigFile (Matt Corallo)
4709ff8 remove now unused gArgs wrappers (Fuzzbawls) cc40f8d Manual prep for gArg wrapper removal (Fuzzbawls) b3c843c scripted-diff: stop using the gArgs wrappers (Fuzzbawls) 5ce3844 Migrate g_logger fields to gArgs (Fuzzbawls) 72a6f56 Track negated arguments in the argument paser. (Fuzzbawls) 3142e1b Add additional tests for GetBoolArg() (Fuzzbawls) 4aef2f3 Fix constness of ArgsManager methods (Fuzzbawls) 13fd27d Fix indentation after 'Remove redundant calls to gArgs.IsArgSet()' (Fuzzbawls) a4114f3 Util: Remove redundant calls to gArgs.IsArgSet() (Fuzzbawls) 92e7227 Util: Small improvements in gArgs usage (Fuzzbawls) a8b26e7 Util: Put mapMultiArgs inside ArgsManager (Fuzzbawls) d2f2e25 scripted-diff: Util: Encapsulate mapMultiArgs behind gArgs (Fuzzbawls) b2abc59 Util: Create ArgsManager class... (Fuzzbawls) 8c4d9c5 Add a ForceSetArg method for testing (Fuzzbawls) 59d6529 Lock mapArgs/mapMultiArgs access in util (Fuzzbawls) f7f2689 Un-expose mapArgs from util.h (Fuzzbawls) 7894b07 Get rid of mapArgs direct access in ZMQ construction (Matt Corallo) b28789f Introduce (and use) an IsArgSet accessor method (Fuzzbawls) 4d8ecf9 Fix non-const mapMultiArgs[] access after init. (Fuzzbawls) 391388d Remove arguments to ReadConfigFile (Fuzzbawls) Pull request description: This is a cumulation of several upstream backports surrounding the argument parsing code. Included here are the following upstream PRs: - bitcoin#9243 - bitcoin#9494 - bitcoin#10118 - bitcoin#10901 - bitcoin#12713 - bitcoin#10607 I've also refactored the global logging argument parsing to match, as that was an "out-of-order" PR that was previously backported to match our previous state. ACKs for top commit: random-zebra: utACK 4709ff8 furszy: cool encapsulation, utACK 4709ff8 and merging Tree-SHA512: 74c8dc1b2280b726eff44855e9908f3563d4ef6493f296ebfafe240ac6470bc45cbc75baac614ed59dfda9e1377b7da7d47a695dfc05e364cada2468bb99a258
zcash: cherry picked from commit 4e04814 zcash: bitcoin/bitcoin#9243
Bitcoin 0.14 locking PRs These are locking changes from upstream (bitcoin core) release 0.14, oldest to newest (when merged to the master branch). Each commit also includes a reference both to the PR and the upstream commit. - bitcoin/bitcoin#8472 - bitcoin/bitcoin#8606 - Excludes a lock move because we don't have bitcoin/bitcoin#7840 which this move was partially-reverting. - bitcoin/bitcoin#9230 - Only first commit (we don't have `LogTimestampStr` anymore). - bitcoin/bitcoin#9243 - Only the sixth commit, excluding `IsArgSet` locking (we haven't pulled that function in yet). - bitcoin/bitcoin#9626 - The cherry-picked commit does not match the upstream at all, but the resulting lock is useful. - bitcoin/bitcoin#9679 - bitcoin/bitcoin#9227 - bitcoin/bitcoin#9698 - Excludes change to `CConnman::PushMessage` in second commit (which we don't have yet). - bitcoin/bitcoin#9708 - bitcoin/bitcoin#9771
This fixes several concurrency issues in mapArgs and mapMultiArgs by making mapMultiArgs const-access-only and hiding mapArgs behind the accessors we already have (+IsArgSet).