Codebase list xapp / 4f4a332
xapp-sn-watcher.c: Don't try to use a null pointer as a hash table lookup key. When a new item tries to register, its key is added to the item table with a null value, to prevent trying to register the same client multiple times. When registration is finished, the key is removed, and re-used to add the new item to the table. If the app disappears before that registration finishes, we remove its key from the table (handle_sn_item_name_owner_lost), so when the item registration completes (it will because a proxy doesn't need an owner), our steal/re-add fails because the key was removed already. This will have us steal the key early when completing registration, and abort if it's null. Also wrap g_object_unref when removing an item from the table to prevent a warning. Michael Webster 3 years ago
1 changed file(s) with 53 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
307307 } NewSnProxyData;
308308
309309 static void
310 free_sn_proxy_data (NewSnProxyData *data)
311 {
312 g_free (data->key);
313 g_free (data->path);
314 g_free (data->bus_name);
315 g_free (data->service);
316 g_object_unref (data->invocation);
317
318 g_slice_free (NewSnProxyData, data);
319 }
320
321 static void
310322 sn_item_proxy_new_completed (GObject *source,
311323 GAsyncResult *res,
312324 gpointer user_data)
321333
322334 proxy = sn_item_interface_proxy_new_finish (res, &error);
323335
336 g_hash_table_steal_extended (watcher->items,
337 data->key,
338 &stolen_ptr,
339 NULL);
340
341 if ((gchar *) stolen_ptr == NULL)
342 {
343 g_dbus_method_invocation_return_error (data->invocation,
344 G_DBUS_ERROR,
345 G_DBUS_ERROR_FAILED,
346 "New StatusNotifierItem disappeared before "
347 "its registration was complete.");
348
349 free_sn_proxy_data (data);
350 g_clear_object (&proxy);
351 return;
352 }
353
324354 if (error != NULL)
325355 {
326356 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
329359 data->bus_name, error->message);
330360 }
331361
332 g_hash_table_steal_extended (watcher->items,
333 data->key,
334 &stolen_ptr,
335 NULL);
336362 g_free (stolen_ptr);
363 free_sn_proxy_data (data);
337364
338365 g_dbus_method_invocation_take_error (data->invocation, error);
339366 return;
341368
342369 item = sn_item_new ((GDBusProxy *) proxy,
343370 g_str_has_prefix (data->path, APPINDICATOR_PATH_PREFIX));
344
345 g_hash_table_steal_extended (watcher->items,
346 data->key,
347 &stolen_ptr,
348 NULL);
349371
350372 g_hash_table_insert (watcher->items,
351373 stolen_ptr,
359381 sn_watcher_interface_complete_register_status_notifier_item (watcher->skeleton,
360382 data->invocation);
361383
362 g_free (data->key);
363 g_free (data->path);
364 g_free (data->bus_name);
365 g_free (data->service);
366 g_object_unref (data->invocation);
367 g_slice_free (NewSnProxyData, data);
384 free_sn_proxy_data (data);
368385 }
369386
370387 static gboolean
493510 }
494511
495512 static void
513 unref_proxy (gpointer data)
514 {
515 // if g_hash_table_remove is called from handle_sn_item_name_owner_lost
516 // *before* sn_item_proxy_new_completed is complete, the key will be
517 // pointing to a NULL value, so avoid trying to free it.
518
519 if (data == NULL)
520 {
521 return;
522 }
523
524 SnItem *item = SN_ITEM (data);
525
526 if (item)
527 {
528 g_object_unref (item);
529 }
530 }
531
532 static void
496533 watcher_startup (GApplication *application)
497534 {
498535 XAppSnWatcher *watcher = (XAppSnWatcher*) application;
503540 xapp_settings = g_settings_new (STATUS_ICON_SCHEMA);
504541
505542 watcher->items = g_hash_table_new_full (g_str_hash, g_str_equal,
506 g_free, g_object_unref);
543 g_free, (GDestroyNotify) unref_proxy);
507544
508545 /* This buys us 30 seconds (gapp timeout) - we'll either be re-held immediately
509546 * because there's a monitor or exit after the 30 seconds. */