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

move --plugins from application to binary #1427 #1437

Merged
merged 16 commits into from
Jan 20, 2019

Conversation

oxarbitrage
Copy link
Member

I am sorry to have to open a new pull request for this ...

Related pulls and history are in: #1427 and #1431

In this one i used the commits from @nathanhourt but moved the plugin option to the executable as suggested by #1431 (comment)

In witness_node/main.cpp all plugins need to be registered: https://github.com/oxarbitrage/bitshares-core/blob/f5031bde96c5f3e20fc71c1d34a519bb417e850d/programs/witness_node/main.cpp#L74-L82 but only the ones from the command line will be enabled: https://github.com/oxarbitrage/bitshares-core/blob/f5031bde96c5f3e20fc71c1d34a519bb417e850d/programs/witness_node/main.cpp#L110 or the default ones: https://github.com/oxarbitrage/bitshares-core/blob/f5031bde96c5f3e20fc71c1d34a519bb417e850d/programs/witness_node/main.cpp#L115-L118

This will at least remove the hardcoded plugins from the application.

I was not able to use register_plugin<>(true) here as they all need to be registered before parsing the command line but only some enabled after it, however i did not removed the option as there is probably a workaround for my code there that can make it simpler by the use of that.

Another thing changed is enable_plugin() member from private to public to be called by the executable.

Let me know what do you guys think as if we go with this approach i will need to do something similar in delayed node.

A few things i also noticed while working on this and related are, probably to consider as new issues:

  • Some plugins(snapshot, witness) add some log msg to the console when they start so you can know they are loaded, others don't do this so you actually dont know from the console if they were loaded or not. I think we should do something for that.
  • The options you add to the command line are ignored in the config file created, for example if you call the node with witness_node --someoption true, then someoption should be the only line not commented in the config file however this is not the case, it loads the default options. Same behaviour without this pull request(not related to this changes).

nathanielhourt and others added 5 commits November 9, 2018 14:54
As far as I can tell, there was no way previously for an application
to register a plugin and ensure that plugin got loaded -- it would
be necessary to manually edit the config and specify the plugin be
loaded.

This is suboptimal; if third party code wishes to track third party
extensions on the blockchain, the correct way to do this is with a
plugin, and this third party build should be able to load these
required plugins regardless of whether the config lists them or not.

This commit adds a boolean parameter to application::register_plugin
which defaults to false for backwards compatibility; however, if
set to true, the plugin will automatically be enabled when the app
initializes.
That code was nasty and... kinda wrong. So fix it up all shiny-like.

But I also removed the super annoying default "wanted" plugins list,
which only causes problems for third parties like me, and in general is
just poor form. In my opinion, 5220425
provides a much cleaner way to do this, in a way that is friendly rather
than hostile to third parties.

Would Be Nice: A generalized plugin conflict system added at the
abstract_plugin level, so, for example, the elasticsearch plugin can
conflict account_history and we deal with this in a general fashion
rather than having this dirty special case check here.
@oxarbitrage
Copy link
Member Author

Found usage to Nathan true flag to fix the cli_test: adef6a2

}
});
}
else {
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps remove this else block and set a default value in line 70 instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

nice one, added at ce35a79

@pmconrad
Copy link
Contributor

So the cli_test crashes were caused by API calls on uninitialized plugins?
We should make sure that such APIs are not accessible.

@pmconrad
Copy link
Contributor

The options you add to the command line are ignored in the config file created, for example if you call the node with witness_node --someoption true, then someoption should be the only line not commented in the config file however this is not the case, it loads the default options. Same behaviour without this pull request(not related to this changes).

IMO the current behaviour is reasonable. The config file contains the usual defaults, and the option given on the command line overrides the config file.

}

if (options.count("plugins")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, isn't this always true now that the option has a default value?

Copy link
Member Author

Choose a reason for hiding this comment

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

sorry about that, you are right, fixed at 58ad814

@pmconrad
Copy link
Contributor

Looks good. @nathanhourt what do you think? Does that satisfy your requirements?

@nathanielhourt
Copy link
Contributor

Yep, this looks reasonable to me.

This was referenced Nov 27, 2018
@abitmore
Copy link
Member

Please update title of this PR to clearer. It's annoying to have to click to another issue/PR to see what this PR is about.

@oxarbitrage oxarbitrage changed the title Another one for pull #1427 move --plugins from application to binary #1427 Nov 28, 2018
pmconrad
pmconrad previously approved these changes Nov 29, 2018
@abitmore
Copy link
Member

This will break the standalone delayed_node binary, no?

@pmconrad pmconrad dismissed their stale review November 30, 2018 17:29

@abitmore you're right.

@pmconrad
Copy link
Contributor

delayed_node compiles and runs but doesn't activate the delayed_node plugin. :-/

@oxarbitrage please adapt delayed_node/main.cpp in the same way.

auto delayed_plug = node.register_plugin<delayed_node::delayed_node_plugin>();
auto history_plug = node.register_plugin<account_history::account_history_plugin>();
auto market_history_plug = node.register_plugin<market_history::market_history_plugin>();
auto delayed_plug = node->register_plugin<delayed_node::delayed_node_plugin>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps auto delayed_plug = node->register_plugin<delayed_node::delayed_node_plugin>(true);?

Copy link
Member Author

Choose a reason for hiding this comment

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

make sense in this context, added. thanks.

@@ -60,7 +60,7 @@ fc::optional<fc::logging_config> load_logging_config_from_ini_file(const fc::pat

int main(int argc, char** argv) {
try {
app::application node;
app::application* node = new app::application();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why? Now you have to delete it when you're done.

Copy link
Member Author

Choose a reason for hiding this comment

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

i actually changed that because of this:

(gdb) r
Starting program: /home/alfredo/CLionProjects/pull1427_2/programs/delayed_node/delayed_node 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
2133844ms th_a       main.cpp:109                  main                 ] Writing new config file at /home/alfredo/CLionProjects/pull1427_2/delayed_node_data_dir/config.ini

Program received signal SIGSEGV, Segmentation fault.
0x0000555557889fdd in graphene::chain::database::close (this=0x55555b83ab70, rewind=true) at /home/alfredo/CLionProjects/pull1427_2/libraries/chain/db_management.cpp:222
222	         uint32_t cutoff = get_dynamic_global_properties().last_irreversible_block_num;
(gdb) bt
#0  0x0000555557889fdd in graphene::chain::database::close (this=0x55555b83ab70, rewind=true) at /home/alfredo/CLionProjects/pull1427_2/libraries/chain/db_management.cpp:222
#1  0x0000555557240b11 in graphene::app::application::~application (this=0x7fffffffda00, __in_chrg=<optimized out>) at /home/alfredo/CLionProjects/pull1427_2/libraries/app/application.cpp:926
#2  0x0000555557003387 in main (argc=1, argv=0x7fffffffde48) at /home/alfredo/CLionProjects/pull1427_2/programs/delayed_node/main.cpp:63
(gdb) 

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, the destructor generates a SIGSEGV and the solution is to avoid calling the destructor? That's evil.
Does the crash also happen without your other changes? If so, this should be kept as-is and fixed properly in another issue. If not you should find the root cause and fix it properly now.

@@ -160,26 +167,24 @@ int main(int argc, char** argv) {
elog("Error parsing configuration file: ${e}", ("e", e.what()));
return 1;
}
if( !options.count("plugins") )
Copy link
Contributor

Choose a reason for hiding this comment

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

You should keep the "plugins" option. We don't want to change the behaviour of the executable.

Copy link
Member Author

Choose a reason for hiding this comment

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

this is done 1326a5c

@oxarbitrage
Copy link
Member Author

In a branch i have handy here based on hardfork without any of the changes:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$ ./programs/delayed_node/delayed_node 
Segmentation fault (core dumped)
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$ 

I didn't know the issue was unrelated to the changes done here until now.

So i did it the way the witness_node binary is done but without deleting. What do you think if we add:

int signal = exit_promise->wait();
ilog("Exiting from signal ${n}", ("n", signal));
node->shutdown_plugins();
node->shutdown();
delete node;
return 0;
} catch( const fc::exception& e ) {
// deleting the node can yield, so do this outside the exception handler
unhandled_exception = e;
}
if (unhandled_exception)
{
elog("Exiting with error:\n${e}", ("e", unhandled_exception->to_detail_string()));
node->shutdown();
delete node;
return 1;
}
in this pull to fix it ?

@pmconrad
Copy link
Contributor

Yes, if that works.
Note that shutdown may be called twice here (same is true in witness_node). But that's an unrelated issue.

@oxarbitrage
Copy link
Member Author

@pmconrad by going more into this i decided to reverse most of the changes done in the delayed node and just make the delayed node plugin to be loaded correctly into the binary. a8020a7

The delayed node haves several issues that are unrelated to the scope of this pull request, for example:

  • plugins option will not work:

in this patch output will be:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ ./programs/delayed_node/delayed_node --plugins "whatever"
Error parsing command line: unrecognised option '--plugins'
Segmentation fault (core dumped)
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ 

in unpatched node:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$ ./programs/delayed_node/delayed_node --plugins "whatever"
Segmentation fault (core dumped)
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$
  • when required trusted node option is needed:

with this pull:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ ./programs/delayed_node/delayed_node
Segmentation fault (core dumped)
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ 

without it:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$ ./programs/delayed_node/delayed_node
Segmentation fault (core dumped)
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$ 
  • this will work in both versions, this is what really matters:
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ ./programs/delayed_node/delayed_node --trusted-node "127.0.0.1:8090"
3331840ms th_a       main.cpp:109                  main                 ] Writing new config file at /home/alfredo/CLionProjects/pull1427_2/delayed_node_data_dir/config.ini
3331845ms th_a       db_management.cpp:174         open                 ] Wiping object_database due to missing or wrong version
3331845ms th_a       object_database.cpp:93        wipe                 ] Wiping object database...
3331845ms th_a       object_database.cpp:95        wipe                 ] Done wiping object databse.
3331845ms th_a       object_database.cpp:106       open                 ] Opening object database from /home/alfredo/CLionProjects/pull1427_2/delayed_node_data_dir/blockchain ...
3331845ms th_a       object_database.cpp:111       open                 ] Done opening object database.
3331847ms th_a       application.cpp:325           operator()           ] Initializing database...
...

version without patch:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1324_3$ ./programs/delayed_node/delayed_node --trusted-node "127.0.0.1:8090"
3278444ms th_a       db_management.cpp:174         open                 ] Wiping object_database due to missing or wrong version
3278444ms th_a       object_database.cpp:93        wipe                 ] Wiping object database...
3278444ms th_a       object_database.cpp:95        wipe                 ] Done wiping object databse.
3278445ms th_a       object_database.cpp:106       open                 ] Opening object database from /home/alfredo/CLionProjects/pull1324_3/delayed_node_data_dir/blockchain ...
3278453ms th_a       object_database.cpp:111       open                 ] Done opening object database.
3278454ms th_a       application.cpp:325           operator()           ] Initializing database...

  • delayed node uses old config functions that are now in config_utils.cpp.
  • etc.

Much of this is unrelated to the scope of this pull(which is already pretty big) so we better treat them somewhere else as you suggested, the important thing to me is that now the delayed node binary of this pull works the same(with the same problems) as the delayed node before.

@oxarbitrage
Copy link
Member Author

There is another case where the unpatched version was working ok while the patched failing.

It is the case when --plugins option is used with 1 of the 3 allowed plugins from the delayed binary(delayed_node account_history market_history).

With 1326a5c both versions will do the same. For example user will want to load delayed node and market history plugin leaving account history out, he can do that now in the patched version.

@jmjatlanta
Copy link
Contributor

These changes look good. I see one comment above that I am unsure that it has been handled. Perhaps it has, but I do not see it.

We should make sure that such APIs are not accessible.

If it has been handled, great. If not, what would be the expected behavior? An exception stating that the function is not available? Or perhaps you cannot even get a pointer to that API to be able to call that function?

std::set<std::string> plugins;
boost::split(plugins, options.at("plugins").as<std::string>(), [](char c){return c == ' ';});

if(plugins.count("account_history") && plugins.count("elasticsearch")) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This check is useless. Elasticsearch is not available in delayed_node.

@@ -58,7 +58,7 @@ delayed_node_plugin::~delayed_node_plugin()
void delayed_node_plugin::plugin_set_program_options(bpo::options_description& cli, bpo::options_description& cfg)
{
cli.add_options()
("trusted-node", boost::program_options::value<std::string>(), "RPC endpoint of a trusted validating node (required for delayed_node)")
("trusted-node", boost::program_options::value<std::string>()->default_value("127.0.0.1:8090"), "RPC endpoint of a trusted validating node (required for delayed_node)")
Copy link
Contributor

Choose a reason for hiding this comment

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

This is probably a bad default because that's usually the port where the node itself will be listening. IMO it's better to leave this option without a default. Users should have to actively choose which node they trust.

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed it back at e198552

I added it because the binary seg faults when starting with no option:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ ./programs/delayed_node/delayed_node 
Segmentation fault (core dumped)
alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ 

It need to be started with trusted node option:

alfredo@alfredo-System-Product-Name:~/CLionProjects/pull1427_2$ ./programs/delayed_node/delayed_node --trusted-node "127.0.0.1:8090"
2348175ms th_a       main.cpp:111                  main                 ] Writing new config file at /home/alfredo/CLionProjects/pull1427_2/delayed_node_data_dir/config.ini
2348180ms th_a       db_management.cpp:174         open                 ] Wiping object_database due to missing or wrong version
2348180ms th_a       object_database.cpp:93        wipe                 ] Wiping object database...
2348180ms th_a       object_database.cpp:95        wipe                 ] Done wiping object databse.

This problem is independent from the changes in this pull request. Another example of segfault in the delayed_node binary can be observed at the end of the output from ./delayed_node --help

As a workaround i tried: app::application* node = new app::application(); before but was later discarded.

I think we can address this issue in a separate pull request in order to dont complicate things too much further.

Let me know what do you think, thanks again.

Copy link
Contributor

Choose a reason for hiding this comment

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

The segfault will be fixed with #1529. It happens because the delayed_node plugin complains about the missing option and then tries to close a database that has never been opened.

Copy link
Member Author

Choose a reason for hiding this comment

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

great, thanks.

@pmconrad
Copy link
Contributor

Good to go now IMO, thanks!

@oxarbitrage
Copy link
Member Author

thanks @pmconrad merging now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants