Skip to content

Commit a05c070

Browse files
Ensure unique AppIndicator IDs per tray instance
Generates a unique AppIndicator ID for each tray instance using process ID and a sequence number to prevent DBus collisions, especially during unit tests. Also improves cleanup logic by unreferencing previous tray objects and menu resources, and sets indicator status to passive before unref to encourage clean DBus unexport.
1 parent 8939109 commit a05c070

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

src/tray_linux.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@
1717
#define IS_APP_INDICATOR APP_IS_INDICATOR ///< Define IS_APP_INDICATOR for app-indicator compatibility.
1818
#endif
1919
#include <libnotify/notify.h>
20-
#define TRAY_APPINDICATOR_ID "tray-id" ///< Tray appindicator ID.
20+
21+
#include <stdio.h>
22+
#include <unistd.h>
23+
24+
// Use a per-process AppIndicator id to avoid DBus collisions when tests create multiple
25+
// tray instances in the same desktop/session.
26+
static unsigned long tray_appindicator_seq = 0;
2127

2228
// local includes
2329
#include "tray.h"
@@ -68,9 +74,23 @@ int tray_init(struct tray *tray) {
6874
if (gtk_init_check(0, NULL) == FALSE) {
6975
return -1;
7076
}
77+
78+
// If a previous tray instance wasn't fully torn down (common in unit tests),
79+
// drop our references before creating a new indicator.
80+
if (indicator != NULL) {
81+
g_object_unref(G_OBJECT(indicator));
82+
indicator = NULL;
83+
}
7184
loop_result = 0;
7285
notify_init("tray-icon");
73-
indicator = app_indicator_new(TRAY_APPINDICATOR_ID, tray->icon, APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
86+
// The id is used as part of the exported DBus object path.
87+
// Make it unique per *tray instance* to prevent collisions inside a single test process.
88+
// Avoid underscores and other characters that may be normalized/stripped.
89+
char appindicator_id[64];
90+
tray_appindicator_seq++;
91+
snprintf(appindicator_id, sizeof(appindicator_id), "trayid%ld%lu", (long) getpid(), tray_appindicator_seq);
92+
93+
indicator = app_indicator_new(appindicator_id, tray->icon, APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
7494
if (indicator == NULL || !IS_APP_INDICATOR(indicator)) {
7595
return -1;
7696
}
@@ -159,11 +179,26 @@ void tray_show_menu(void) {
159179
}
160180

161181
static gboolean tray_exit_internal(gpointer user_data) {
182+
(void) user_data;
183+
162184
if (currentNotification != NULL && NOTIFY_IS_NOTIFICATION(currentNotification)) {
163185
int v = notify_notification_close(currentNotification, NULL);
164186
if (v == TRUE) {
165187
g_object_unref(G_OBJECT(currentNotification));
166188
}
189+
currentNotification = NULL;
190+
}
191+
192+
if (current_menu != NULL) {
193+
g_object_unref(current_menu);
194+
current_menu = NULL;
195+
}
196+
197+
if (indicator != NULL) {
198+
// Make the indicator passive before unref to encourage a clean DBus unexport.
199+
app_indicator_set_status(indicator, APP_INDICATOR_STATUS_PASSIVE);
200+
g_object_unref(G_OBJECT(indicator));
201+
indicator = NULL;
167202
}
168203
notify_uninit();
169204
return G_SOURCE_REMOVE;

0 commit comments

Comments
 (0)