Rename C++ header files to .hpp Rename all C++ header files (include/**/*-internal.h, src/**/*.h except argpar and msgpack, some headers in tests) to have the .hpp extension. Doing so highlights that we include some C++ header files in some test files still compiled as C. This is ok for now, as the files they include don't actually contain C++ code incompatible with C yet, but they could eventually. This is something we can fix later. Change-Id: I8bf326b6b2946a3e26704f3ef3ac5831bbe9bc26 Signed-off-by: Simon Marchi <simon.marchi@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
liblttng-ctl: use export list to define exported symbols Symbols are currently exported by default by liblttng-ctl.so (usable by other shared libraries / programs using liblttng-ctl.so), so we must use LTTNG_HIDDEN on all symbols that are meant to be internal to liblttng-ctl.so. Of course, this is easy to forget, so over the years many symbols that were not meant to be exported were exported, and must now stay exported to avoid breaking the ABI. As explained here [1], a better method is to make symbols hidden by default, and mark those we want to be exported as such. I have tried to use this, but when subsequently converting the code to C++, I have noticed that some symbols related to the STL were exported anyway, which is bad. The other alternative, implemented in this patch, is to use an explicit symbol export list [2], using libtool's -export-symbols (which uses the linker's -version-script option). Only the symbols listed here are exported. So, in practice, this patch: - Adds an liblttng-ctl.sym file with the list of exported symbols and adjusts the Makefile to use the -export-symbol option - Removes LTTNG_HIDDEN and all its uses abidiff shows no changes for liblttng-ctl.so between before and after this patch. [1] https://gcc.gnu.org/wiki/Visibility [2] https://www.gnu.org/software/libtool/manual/libtool.html#Link-mode Change-Id: I5d8c558303894b0ad8113c6e52f79a053bb580e1 Signed-off-by: Simon Marchi <simon.marchi@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Fix: sessiond: list-triggers: don't return internal triggers The session daemon uses triggers internally. For instance, the trigger and notification subsystem is used to implement the automatic rotation of sessions based on a size threshold. Currently, a user of the C API will see those internal triggers if it is running as the same user as the session daemon. This can be unexpected by user code that assumes it will be alone in creating triggers. Moreover, it is possible for external users to unregister those triggers which would cause bugs. As the triggers gain more capabilities, it is likely that the session daemon will keep using them to implement features internally. Thus, an internal "is_hidden" property is introduced in lttng_trigger. A "hidden" trigger is a trigger that is not returned by the listings. It is used to hide triggers that are used internally by the session daemon so that they can't be listed nor unregistered by external clients. This is a property that can only be set internally by the session daemon. As such, it is not serialized nor set by a "create_from_buffer" constructor. The hidden property is preserved by copies. Note that notifications originating from an "hidden" trigger will not be sent to clients that are not within the session daemon's process. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I61b7949075172fcd428289e2eb670d03c19bdf71
Docs: sessiond: document the rationale for the iteration on triggers list Document the reason why an iteration is performed on the list of triggers of a "client list" when a client subscribes to a condition. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I7d1c15016064ff2f6498c925f4933450fc7da30b
notification: transmit originating trigger as part of evaluation Transmit the full trigger object instead of its condition when sending a notification to a client. This allows clients to reliably filter on triggers as, currently, only the name of a trigger is made available to clients as part of the "on_event" evaluation object (the owner uid is needed to perform a correct comparison for filtering). This will also make the trigger accessible for all condition types. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I61d587436177eb34744487a1d3c486d87fe2e1f1
Fix: sessiond: notification: use after free of trigger object Background ========== * Clients can subscribe to certain specific conditions (e.g. buffer usage) using the `lttng_notification_channel_subscribe()` function. * This subscription is only useful once a trigger with that condition AND at least one notify action is registered. * The sessiond keeps a list for client subscribed to each registered condition. * More than one trigger with the same condition may be registered the sessiond at the same time if they have different actions. Issue ===== Currently, when registering a trigger (T1) the sessiond looks if there is already a client list for the condition of this trigger. If not, the sessiond links the newly created client list object to that trigger T1 by keeping a pointer to it. This means that if another trigger (T2) is registered with the same condition (but a different name, or different actions) it will reuse the same client list object and use the pointer to the T1. This causes problems if T1 is unregistered before T2. In that case, the pointer to T1 in the client list object is pointing to a deallocated trigger object. This issue is not encountered with the current test suite, namely the `test_notification_multi_app` test case, because triggers with the same condition also had the same action, so they are considered identical and are not registered. This issue was first witnessed when adding a trigger name comparison in the `lttng_trigger_is_equal()` function. Fix === Change the client list object so that it has its own copy of the condition and a list of dependent triggers. Each trigger with that condition has a reference on this client list object. When unregistering a trigger, the notification thread removes it for the client list's triggers list and put its reference on the client list object. Tests ===== This commit adds a parameter to the base_client that dictates if the notify action should be in a group. This is a trick to create triggers that are not equal but have the same behaviour. The `test_notification_multi_app` test case is modified to turn on this option every other trigger registration. Semi-related cleanups ===================== * Merge `notification_client_list_create()` and `publish_notification_client_list()` functions since they are used together anyway. This removes the need to call `notification_client_list_put()` at the end of the `_register_trigger()` function * Rename `trigger_applies_to_client()` to `condition_applies_to_client()`. Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I3ebb90a1a64236a440a085e6fc1b82726a0e5af9
notification: fetch capture payload on notification reception Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: Id52749b59969276b5390f4494df48940662d5d8c
Implements `lttng_event_notifier_notification_{create,destroy}()` Capture payload will be later added to the lttng_event_notifier_notification object. Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I404984c522cdf46c0df7c6ffbbe340d2f56cda2d Depends-on: lttng-ust: I8423c510bf6af2f9bf85256e8d6f931d36f7054b
sessiond: notification: use lttng_payload for communications Allows passing of fds related to object (e.g userspace probes). Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I7bb3a91c71016b2939b0e05aca60d57c2da14a20
Fix: sessiond: client/client_list lock inversion on disconnect Coverity reports a lock inversion scenario in handle_notification_thread_client_disconnect() where a client's lock is held while acquiring the client list lock. This is indeed a problem. As indicated in the notification_client and notification_client_list comments, the locking was shoe-horned to make it possible for the action executor to enqueue notifications in a client's outgoing queue and flush it. Since this is the only access pattern that is supported, the client locking is reworked slightly to only acquire the client lock when checking the "active" flag, interacting with the outbound communication state, and sending through a client's socket. This change makes the client locking regions more narrow which accounts for the somewhat large number of lines affected. The updates to the `active` flag on error are moved to the function that flushes the outbound queue instead of expecting the callers to set it. This allows the locking to be limited to this function rather than relying on the callers. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I8632d0f7785ec727dabd329bdfba010fd5e4643a
sessiond: trigger: run trigger actions through an action executor The `action executor` interface allows the notification subsystem to enqueue work items to execute on behalf of a given trigger. This allows the notification thread to remain responsive even if the actions to execute are blocking (as through the use of network communication). Before this commit, the notification subsystem only handled `notify` actions; handling code for new action types are added as part of the action executor. The existing `notify` action is now performed through the action executor so that all actions can be managed in the same way. This is less efficient than sending the notifications directly, but could be optimized trivially (if it ever becomes a problem) when: - the action is a group containing only a `notify` action, - the action is a `notify` action. Overview of changes to existing code === Managing the new action types requires fairly localized changes to the existing notification subsystem code. The main code paths that are modified are the sites where `evaluation` objects are created: 1) on an object state change (session or channel state changes, see handle_notification_thread_channel_sample and handle_notification_thread_command_session_rotation), 2) on registration of a trigger (see handle_notification_thread_command_register_trigger), 3) on subscription to a condition (see client_handle_message_subscription). To understand the lifetime of most objects involved in a work deferral to the action executor, see the paragraph in notification-thread-internal.h (line 82) to understand the relation between clients and client lists. 1) Object state changes As hinted in the notification_client_list documentation, deferring work on a state change is straight-forward: a reference is taken on a client list and the list is provided to the action executor as part of a work item. Hence, very little changes are made to the the two state-change handling sites beyond enqueuing a work item rather than directly sending a notification. 2) Subscription to a condition A notification client can subscribe to a condition before or after a matching trigger (same condition and containing a notify action) has been registered. If no matching trigger were registered, no client list exists and there is nothing to do. If a matching trigger existed, a client list (which could be empty) will already exist and the client is simply added to the client list. However, it is important to evaluate the condition for the client (as the condition could already be true) and send the notification to that client only and not to all clients in the list. Before this change, since everything was done in the same thread, a temporary list containing only the newly-subscribed client was created on the stack and the notification was sent/queued immediately. After sending the condition, the client was removed from the temporary list and added to the "real" client list. This strategy cannot be used with the action executor as the "temporary" client list must exist beyond the scope of the function. Moreover, the notification subsystem assumes that clients are in per-condition client lists and that they can safely be destroyed when they are not present in any list. Fortunately, here we know that the action to perform is to `notify` and nothing else. The enqueuing of the notification is performed "in place" by the notification thread without deferring to the action executor. 3) Registration of a trigger When a client subscribes to a condition, the current state of that condition is immediately evaluated. If the condition is true (for instance, a channel's buffer are filled beyond X% of their capacity), the action associated with the trigger is executed right away. This path requires little changes as a client list is created when a trigger is registered. Hence, it is possible to use the client list to defer work as is done in `1`. 4) Trigger registration Since the `notify` action was the only supported action type, the notification subsystem always created a client list associated with the new trigger's condition. This is changed to only perform the creation (and publication) of the client list if the trigger's action is (or contains, in the case of a group) a `notify` action. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I43b54b93c1244591aeff6e0d0fa8076c7b5e0c50
Revert "sessiond: trigger: run trigger actions through an action executor" This reverts commit d1ba29d290281cf72ca3ec7b0222b336c747e925. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I70d57fef86aea94a590720689af751e2554184d0
sessiond: trigger: run trigger actions through an action executor The `action executor` interface allows the notification subsystem to enqueue work items to execute on behalf of a given trigger. This allows the notification thread to remain responsive even if the actions to execute are blocking (as through the use of network communication). Before this commit, the notification subsystem only handled `notify` actions; handling code for new action types are added as part of the action executor. The existing `notify` action is now performed through the action executor so that all actions can be managed in the same way. This is less efficient than sending the notifications directly, but could be optimized trivially (if it ever becomes a problem) when: - the action is a group containing only a `notify` action, - the action is a `notify` action. Managing the new action types requires fairly localized changes to the existing notification subsystem code. The main code paths that are modified are the sites where `evaluation` objects are created: - on an object state change (session or channel state changes, see handle_notification_thread_channel_sample and handle_notification_thread_command_session_rotation), - on registration of a trigger (see handle_notification_thread_command_register_trigger), - on subscription to a condition (see client_handle_message_subscription). To understand the lifetime of most objects involved in a work deferral to the action executor, see the paragraph in notification-thread-internal.h (line 82) to understand the relation between clients and client lists. Overview of changes === Object state changes Change-Id: I23290e94d98e781992661f0aee88de9986ed274f --- As hinted in the notification_client_list documentation, defering work on a state change is straight-forward: a reference is taken on a client list and the list is provided to the action executor as part of a work item. Hence, very little changes are made to the the two state-change handling sites beyond enqueuing a work item rather than directly sending a notification. Subscription to a condition --- A notification client can subscribe to a condition before or after a matching trigger (same condition and containing a notify action) has been registered. When a client subscribes to a condition, it is a added to a corresponding "client list" Registration of a trigger --- When a client subscribes to a condition, the current state of that condition is immediately evaluated. If the condition is true (for instance, a channel's buffer are filled beyond X% of their capacity), TODO: Change-Id: I7f9bc197715c9ca008a4f1fcd4c86e01b6252dce Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
sessiond: notification: refactor: split transmission and poll update Split the notification transmission logic and its effect on a notification_client from the logic tied to the management of the notification thread. This is to make it possible to send (or queue) notifications from the notification thread or another thread. If another thread encounters an error or a full socket buffer, a future mechanism will allow it to signal the notification thread to update its private state (e.g. poll mask). Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Change-Id: I35d8943cb11473d82b07a4dbc5a0f093cde25a79
Move to kernel style SPDX license identifiers The SPDX identifier is a legally binding shorthand, which can be used instead of the full boiler plate text. See https://spdx.org/ids-how for details. Signed-off-by: Michael Jeanson <mjeanson@efficios.com> Change-Id: I62e7038e191a061286abcef5550b58f5ee67149d Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Fix: notification thread: RCU-safe reclaim of hash table nodes Nodes that are put in a rculfhash hash table created with the "auto resize" flag need to beware that a worker thread can access the hash table nodes as a RCU reader concurrently, and that this worker thread can modify the hash table content, effectively adding and removing "bucket" nodes, and changing the size of the hash table index. Therefore, even though only a single thread reads and updates the hash table, a grace period is needed before reclaiming the memory holding the rculfhash nodes. Moreover, handle_notification_thread_command_add_channel() misses a RCU read-side lock around iteration on the triggers hash table. Failure to hold this read-side lock could cause segmentation faults when accessing hash table objects if a hash table resize is done by the worker thread in parallel with iteration over the hash table. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Build a list of triggers applying to a given session on creation A hash table associating session names (which are unique) to a lttng_session_trigger_list object is added to the notification subsystem. This hash table is populated on the creation of a session and a list is initialized with matching triggers known at that time. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>