Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

notification: dbus transport plugins #1825

Merged
merged 54 commits into from
Mar 24, 2018

Conversation

waht
Copy link
Contributor

@waht waht commented Feb 23, 2018

Purpose

This PR contains dbus transport plugins for the notification feature.

Checklist

  • dbus[send] plugin (adds asynchronous sending of notifications to existing dbus plugin)
  • dbusrecv plugin (asynchronous receiving of notifications via dbus)
  • commit messages are fine (with references to issues)
  • I added unit tests
  • affected documentation is fixed
  • I ran all tests and everything went fine
  • I added code comments, logging, and assertions (see doc/CODING.md)
  • release notes are updated (doc/news/_preparation_next_release.md)
  • find and fix memory leak (Test for Notification Library Causes Memory Leaks #1824)
  • dbusrecv: add support for "Commit" signals
  • notification: check registered keys on notifications
  • architecture: improve plugin callbacks

@waht waht self-assigned this Feb 23, 2018
src/libs/io/io.c Outdated
* @param name Function name
* @return Pointer to function
*/
static size_t getPluginFunction (Plugin * plugin, const char * name)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@markus2330: Is there a way to share functions like these internally (e.g. with libraries and plugins) and not export them? I feel like I'm missing some obvious choice here :)

Copy link
Contributor

Choose a reason for hiding this comment

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

To share a library function (in any way outside of the source file/library itself) requires the function to be exported (including the c file is a hack only suitable for tests).

To share a function in a plugin you can use the contract (the exports). Of course you could realize something similar for your library but that most likely is overkill.

Btw. do you know elektraInvokeGetFunction from the elektra-invoke library implemented in src/libs/invoke/invoke.c?
It looks very similar to your code.

Copy link
Contributor Author

@waht waht Feb 24, 2018

Choose a reason for hiding this comment

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

Ok, thank you very much!

Yes I have seen it, but it uses ElektraInvokeHandle which wraps Plugin. I'm using getPluginFunction at various points where I directly have a Plugin handle available (like when iterating global plugins or passing the I/O binding to list's subplugins and in the notification library to access register*-functions).

How about adding this particular function to libplugin as elektraPluginGetFunction?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this is a very good idea!

I am even thinking about making elektra-invoke dependent on elektra-plugin to use your function. Both getPluginFunction and elektraInvokeGetFunction are lacking the optimization to directly use plugin->kdb* when requesting one of the 5 standard functions (open, close, get, set, error).

If we add the dep to elektra-plugin from elektra-invoke we could get rid of any access to Plugin's struct within elektra-invoke, making elektra-invoke independent of internals of the Plugin's struct. elektra-plugin obviously needs by design access to the struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, great! I will add it to libplugin.

I can make the changes to elektra-invoke later on within this PR.

src/libs/io/io.c Outdated
return func;
}

static void debugKeySet (char * name, KeySet * ks)
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! I better enable -Werror to get these messages locally too.


void elektraNotificationDoUpdate (Key * key, void * data)
{
KDB * kdb = (KDB *)data;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@markus2330 plugins get this callback passed on "openNotification" (exported function by plugin). the additional callback data (of type void *) is a KDB handle. Since I need to call kdbGet() the handle is required.

I'm not sure if this can be bypassed. Maybe passing a struct that wraps the handle to mask it, but that's security by obscurity :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Why is void* used instead of KDB*?

Yes, it can make sense to have an extra struct, then you can pass more than a KDB* handle to the callback.

In any case: This is a question of API design. Why should it be related to security?

Copy link
Contributor Author

@waht waht Feb 25, 2018

Choose a reason for hiding this comment

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

I haven't decided about the struct but didn't want to use KDB so I used void for now.

I thought in our discussion on why KBD was not in Plugin security was the problem.

If having KDB passed in a struct to plugins is not an issue, I'll use a struct to keep the API easier to maintain.

@waht
Copy link
Contributor Author

waht commented Feb 25, 2018

I would like to add automated tests for the dbus plugins. This requires either mocking of the dbus library functions or having a dbus daemon running on the build server.
It is possible to start dbus manually with dbus-daemon --system (as root at least).
What do you think, @sanssecours @markus2330?

@sanssecours
Copy link
Member

It is possible to start dbus manually with dbus-daemon --system (as root at least).

At least on macOS (Travis) you should be able to start dbus with brew services start dbus. Starting dbus with

sudo dbus-daemon --system

fails with the message

dbus-daemon[94768]: Failed to start message bus: Could not get UID and GID for username "messagebus"

, at least on my machine. Maybe the same command works on the Linux Travis build jobs. Anyway, I would just recommend you try it.

If you think the build times are too long, I would recommend you just remove most of the code in travis.yml, register with your GitHub account at http://travis-ci.org and try to change .travis.yml at your copy of the repo. This way you do not have to share the Travis resources with the other Elektra developers here.

@markus2330
Copy link
Contributor

Installing dbus on the Jenkins agents is no problem, I suppose most agents already have dbus.

In any case, it would be good if you check within tests if dbus is available and stop the test if it won't work.

@waht
Copy link
Contributor Author

waht commented Feb 27, 2018

Ok great! Thanks for looking into it and for the tip, @sanssecours! Build times should not be affected (unless I need dbus needs to be compiled of course), but my own Travis account is probably useful until I figure out the build setup.

@markus2330 Sure, I will make the tests fail with a warning if dbus is not available.

@markus2330
Copy link
Contributor

Sure, I will make the tests fail with a warning if dbus is not available.

Please succeed with warning. If test cases do not run through, people won't run them.

@waht waht force-pushed the notification_dbus branch 2 times, most recently from 83c3d5c to e1a0efe Compare March 1, 2018 12:55
@waht
Copy link
Contributor Author

waht commented Mar 1, 2018

The dbus plugin tests now only fail when no D-Bus connection (neither system nor session bus) was possible. On MacOs the tests use the session bus, on Linux the system bus.

You were talking about having a warning (i.e. a printf) and skipping the further tests, right? My concern is that the warning would not be visible when running the tests with run_all & co.

@markus2330 please review my pull request - I'll go hunting for the memory leak from #1824 :)

@@ -45,7 +45,7 @@ function (add_plugintest testname)
restore_variable (${PLUGIN_NAME} ARG_COMPILE_DEFINITIONS)
restore_variable (${PLUGIN_NAME} ARG_INCLUDE_DIRECTORIES)
restore_variable (${PLUGIN_NAME} ARG_INCLUDE_SYSTEM_DIRECTORIES)
restore_variable (${PLUGIN_NAME} ARG_LINK_ELEKTRA)
restore_variable (${PLUGIN_NAME} ARG_LINK_ELEKTRA ALLOW_MATCH)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@markus2330 the dbusrecv plugin required io_uv for testing: While the dbusrecv plugin relies on the ElektraIoInterface, to test the code a I/O binding was required.

I relaxed the consistency checks so that add_plugintest allows additional libraries. The plugin libraries still need to be included.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would be better if we can avoid circular deps.

If we really would need such a hack, we should introduce LINK_LIBRARIES_CIRCULAR or similar which adds the ALLOW_MATCH (the name ALLOW_MATCH is not really good, too?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why would the deps be circluar?
It allows to add additional libraries for plugin tests.

If we really would need such a hack, we should introduce LINK_LIBRARIES_CIRCULAR or similar which adds the ALLOW_MATCH (the name ALLOW_MATCH is not really good, too?)

Okay. How about LINK_LIBRARIES_ADDITIONAL and "ALLOW_ADDITIONAL"?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh, I misunderstood what you are trying to achieve.

Yes, fresh names are a much better solution. What about UNITTEST_LINK_LIBRARIES? (ADDITIONAL is too generic, then it is unclear -- like it was for me -- that you only need it for the tests.)

@waht
Copy link
Contributor Author

waht commented Mar 1, 2018

jenkins build all please

@waht
Copy link
Contributor Author

waht commented Mar 2, 2018

jenkins build gcc-configure-debian-musl please

@waht
Copy link
Contributor Author

waht commented Mar 2, 2018

jenkins build multiconfig-gcc47-cmake-options please

@waht
Copy link
Contributor Author

waht commented Mar 2, 2018

jenkins build gcc-configure-debian-musl please

@waht
Copy link
Contributor Author

waht commented Mar 2, 2018

jenkins build all please

@waht
Copy link
Contributor Author

waht commented Mar 7, 2018

Okay, we've located the source for the memleak in #1824: The ubsan library was missing - the workaround (preloading it) is included in this PR or should be wait for the process plugin PR (#1783) which includes this fix as well?

@markus2330
Copy link
Contributor

@e1528532 Any plans to finish #1783?

In any case: if you git cherry-pick a fix or your fix is identical (char-by-char) there is no problem if it is applied twice.

@waht waht force-pushed the notification_dbus branch from 0c0badc to 4916e9f Compare March 8, 2018 10:24
@waht
Copy link
Contributor Author

waht commented Mar 8, 2018

Ok I realized that we have a similar issue (and curiously the same missing symbol __ubsan_vptr_type_cache) which is fixed by preloading different libraries.

In order to resolve my issue preloading the UbSan c++ library is required. The ASan library (as in #1783) does not work for me (the output says ==28==Your application is linked against incompatible ASan runtimes.).

I changed my PR so that it is possible to preload multiple libraries.

@waht
Copy link
Contributor Author

waht commented Mar 8, 2018

jenkins build haskell please

1 similar comment
@sanssecours
Copy link
Member

jenkins build haskell please

@sanssecours
Copy link
Member

jenkins build docker please

@waht waht force-pushed the notification_dbus branch from a44b35b to 1d88561 Compare March 18, 2018 17:37
@waht
Copy link
Contributor Author

waht commented Mar 21, 2018

Okay. I've improved the decision and moved the new functions to elektra-invoke.

@waht
Copy link
Contributor Author

waht commented Mar 21, 2018

jenkins build all please

@waht
Copy link
Contributor Author

waht commented Mar 21, 2018

Obviously the dbus tests fail without the daemon. Shall we wait until the build agents are updated or simply make the tests print a warning and exit normally?

@markus2330
Copy link
Contributor

Shall we wait until the build agents are updated or simply make the tests print a warning and exit normally?

Yes, that is okay. I even wrote that 22 days ago, see above ("Please succeed with warning. If test cases do not run through, people won't run them.").

@waht waht mentioned this pull request Mar 21, 2018
9 tasks
@waht
Copy link
Contributor Author

waht commented Mar 21, 2018

Ah I see :) I will change the tests accordingly.

@waht
Copy link
Contributor Author

waht commented Mar 22, 2018

jenkins build all please

@waht
Copy link
Contributor Author

waht commented Mar 23, 2018

jenkins build all please

@markus2330
Copy link
Contributor

I'll check the PRs asap. Is there any order I need to merge them?

Copy link
Contributor

@markus2330 markus2330 left a comment

Choose a reason for hiding this comment

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

only typos and some small questions

Can be fixed in one of the following PRs.


Encapsulating plugins export a function called `deferredCall` with the
declaration
`void ElektraDeferredCall (Plugin * plugin, char * name, KeySet * parameters)`.
Copy link
Contributor

Choose a reason for hiding this comment

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

E should be lower case

The called function receive their parameters via a KeySet.

While called functions could return data using the `parameters` KeySet (or a
seperate KeySet) there is no defined moment when the data can be collected.
Copy link
Contributor

Choose a reason for hiding this comment

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

separate


Plugins that support deferred calls shall have the following declaration for
their functions
`void ElektraDeferredCallable (Plugin * plugin, KeySet * parameters)`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't the absence of deferredCall already tell? What are the parameters for?


## Related decisions

- Elektra's invoke functionality will be extended to also allow use of deferred
Copy link
Contributor

Choose a reason for hiding this comment

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

allow us to use

It is recommended to use callbacks passed as `parameters`.
The callback function declaration is not affected by this decision.

## Related decisions
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this also already implemented? Why related decision?

{
DBusConnection * connection = priv->connection;

// TODO currently not possible because dbus uses multiple watches for the same fd
Copy link
Contributor

Choose a reason for hiding this comment

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

todo

@@ -19,6 +21,9 @@ int elektraListSet (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraListError (Plugin * handle, KeySet * ks, Key * parentKey);
int elektraListAddPlugin (Plugin * handle, KeySet * pluginConfig);
int elektraListEditPlugin (Plugin * handle, KeySet * pluginConfig);
void elektraListSetIoBinding (Plugin * handle, ElektraIoInterface * binding);
Copy link
Contributor

Choose a reason for hiding this comment

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

I could not find the comment below anymore. Can you describe the deps somewhere explicitly?

@markus2330 markus2330 merged commit 39c9451 into ElektraInitiative:master Mar 24, 2018
@markus2330
Copy link
Contributor

Thank you, great work!

I added some small comments to be fixed in a later PR.

@e1528532 e1528532 mentioned this pull request Aug 6, 2018
5 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants