From fb7a71da202632c7301ada67c8b4420bfb8d8fbe Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 15 Jan 2008 21:40:15 -0500 Subject: can tell when a window that was "closed" has stopped responding now --- openbox/ping.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 openbox/ping.c (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c new file mode 100644 index 00000000..d8c10c83 --- /dev/null +++ b/openbox/ping.c @@ -0,0 +1,151 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + client.h for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2008 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "ping.h" +#include "client.h" +#include "prop.h" +#include "event.h" +#include "mainloop.h" +#include "openbox.h" + +typedef struct _ObPingTarget +{ + ObClient *client; + ObPingEventHandler h; + Time sent; + gint waiting; +} ObPingTarget; + +static GSList *ping_targets = NULL; +static gboolean active = FALSE; + +#define PING_TIMEOUT (G_USEC_PER_SEC * 1) +/*! Warn the user after this many PING_TIMEOUT intervals */ +#define PING_TIMEOUT_WARN 3 + +static void ping_send(ObPingTarget *t); +static void ping_end(ObClient *client, gpointer data); +static gboolean ping_timeout(gpointer data); + +void ping_start(struct _ObClient *client, ObPingEventHandler h) +{ + GSList *it; + ObPingTarget *t; + + /* make sure we're not already pinging it */ + for (it = ping_targets; it != NULL; it = g_slist_next(it)) { + t = it->data; + if (t->client == client) return; + } + + t = g_new(ObPingTarget, 1); + t->client = client; + t->h = h; + t->waiting = 1; /* first wait for a reply */ + + ping_send(t); + ping_targets = g_slist_prepend(ping_targets, t); + ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, + t, NULL, NULL); + + if (!active) { + active = TRUE; + /* listen for the client to disappear */ + client_add_destroy_notify(ping_end, NULL); + } +} + +void ping_stop(struct _ObClient *c) +{ + ping_end(c, NULL); +} + +void ping_got_pong(Time timestamp) +{ + GSList *it; + ObPingTarget *t; + + /* make sure we're not already pinging it */ + for (it = ping_targets; it != NULL; it = g_slist_next(it)) { + t = it->data; + if (t->sent == timestamp) { + ob_debug("Got PONG with timestamp %lu\n", timestamp); + if (t->waiting > PING_TIMEOUT_WARN) { + /* we had notified that they weren't responding, so now we + need to notify that they are again */ + t->h(t->client, FALSE); + } + t->waiting = 0; /* not waiting for a reply anymore */ + break; + } + } + + if (it == NULL) + ob_debug("Got PONG with timestamp %lu but not waiting for one\n", + timestamp); +} + +static void ping_send(ObPingTarget *t) +{ + t->sent = event_get_server_time(); + ob_debug("PINGing client 0x%x at %lu\n", t->client->window, t->sent); + PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, + prop_atoms.net_wm_ping, t->sent, t->client->window, 0, 0, + NoEventMask); +} + +static gboolean ping_timeout(gpointer data) +{ + ObPingTarget *t = data; + + if (t->waiting == 0) { /* got a reply already */ + /* send another ping to make sure it's still alive */ + ping_send(t); + } + + if (t->waiting == PING_TIMEOUT_WARN) + t->h(t->client, TRUE); /* notify that the client isn't responding */ + + ++t->waiting; + + return TRUE; /* repeat */ +} + +static void ping_end(ObClient *client, gpointer data) +{ + GSList *it; + ObPingTarget *t; + + for (it = ping_targets; it != NULL; it = g_slist_next(it)) { + t = it->data; + if (t->client == client) { + ping_targets = g_slist_remove_link(ping_targets, it); + ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, + FALSE); + g_free(t); + break; + } + } + + /* stop listening if we're not waiting for any more pings */ + if (!ping_targets) { + active = TRUE; + client_remove_destroy_notify(ping_end); + } +} -- cgit v1.2.3 From d3e9fc8941831477b50678b9bd676e29f4bed1a7 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 15 Jan 2008 21:57:47 -0500 Subject: show [Not Responding] in the titlebar when closing an app and it stops responding to pings --- openbox/ping.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index d8c10c83..687dd7f4 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -48,6 +48,8 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h) GSList *it; ObPingTarget *t; + g_assert(client->ping == TRUE); + /* make sure we're not already pinging it */ for (it = ping_targets; it != NULL; it = g_slist_next(it)) { t = it->data; -- cgit v1.2.3 From 810afd8597da355039e289218abed6c062585870 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 15 Jan 2008 22:34:04 -0500 Subject: ping all the windows every 3 seconds, and show "not responding" if they stop replying for 3 times (9-12 seconds). show [Killing...] in the titlebar when trying to kill an app off --- openbox/ping.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 687dd7f4..874d020c 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -35,7 +35,7 @@ typedef struct _ObPingTarget static GSList *ping_targets = NULL; static gboolean active = FALSE; -#define PING_TIMEOUT (G_USEC_PER_SEC * 1) +#define PING_TIMEOUT (G_USEC_PER_SEC * 3) /*! Warn the user after this many PING_TIMEOUT intervals */ #define PING_TIMEOUT_WARN 3 @@ -87,7 +87,7 @@ void ping_got_pong(Time timestamp) for (it = ping_targets; it != NULL; it = g_slist_next(it)) { t = it->data; if (t->sent == timestamp) { - ob_debug("Got PONG with timestamp %lu\n", timestamp); + /*ob_debug("Got PONG with timestamp %lu\n", timestamp);*/ if (t->waiting > PING_TIMEOUT_WARN) { /* we had notified that they weren't responding, so now we need to notify that they are again */ @@ -106,7 +106,7 @@ void ping_got_pong(Time timestamp) static void ping_send(ObPingTarget *t) { t->sent = event_get_server_time(); - ob_debug("PINGing client 0x%x at %lu\n", t->client->window, t->sent); + /*ob_debug("PINGing client 0x%x at %lu\n", t->client->window, t->sent);*/ PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->sent, t->client->window, 0, 0, NoEventMask); -- cgit v1.2.3 From f9f32d9fbaae9ca415603bb61b36393994afbd16 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 15 Jan 2008 22:51:04 -0500 Subject: cant consistently tell if we should use WM_DESTROY after the first time they try close a window.. so just kill when "not responding" is showing --- openbox/ping.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 874d020c..531b8938 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -87,7 +87,8 @@ void ping_got_pong(Time timestamp) for (it = ping_targets; it != NULL; it = g_slist_next(it)) { t = it->data; if (t->sent == timestamp) { - /*ob_debug("Got PONG with timestamp %lu\n", timestamp);*/ + ob_debug("Got PONG with timestamp %lu for %s\n", timestamp, + t->client->title); if (t->waiting > PING_TIMEOUT_WARN) { /* we had notified that they weren't responding, so now we need to notify that they are again */ @@ -106,7 +107,7 @@ void ping_got_pong(Time timestamp) static void ping_send(ObPingTarget *t) { t->sent = event_get_server_time(); - /*ob_debug("PINGing client 0x%x at %lu\n", t->client->window, t->sent);*/ + ob_debug("PINGing client %s at %lu\n", t->client->title, t->sent); PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->sent, t->client->window, 0, 0, NoEventMask); -- cgit v1.2.3 From 7bd8e97fbb751f2a4b9b4feea140a703540bc4e3 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 15 Jan 2008 22:56:24 -0500 Subject: rework and comment out some debugging prints --- openbox/ping.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 531b8938..daabbfb5 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -87,8 +87,8 @@ void ping_got_pong(Time timestamp) for (it = ping_targets; it != NULL; it = g_slist_next(it)) { t = it->data; if (t->sent == timestamp) { - ob_debug("Got PONG with timestamp %lu for %s\n", timestamp, - t->client->title); + /*ob_debug("PONG: '%s' (timestamp %lu)\n", t->client->title, + t->sent);*/ if (t->waiting > PING_TIMEOUT_WARN) { /* we had notified that they weren't responding, so now we need to notify that they are again */ @@ -107,6 +107,7 @@ void ping_got_pong(Time timestamp) static void ping_send(ObPingTarget *t) { t->sent = event_get_server_time(); + /*ob_debug("PING: '%s' (timestamp %lu)\n", t->client->title, t->sent);*/ ob_debug("PINGing client %s at %lu\n", t->client->title, t->sent); PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->sent, t->client->window, 0, 0, -- cgit v1.2.3 From cfc8101333535e3336eff5e929839c5262231db6 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Tue, 15 Jan 2008 23:28:30 -0500 Subject: don't let repeating timers, with a very fast timer in the queue, cause the main loop to run the timers forever --- openbox/ping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index daabbfb5..d159805d 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -64,7 +64,7 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h) ping_send(t); ping_targets = g_slist_prepend(ping_targets, t); ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, - t, NULL, NULL); + t, g_direct_equal, NULL); if (!active) { active = TRUE; -- cgit v1.2.3 From ff78d28f8bcdbbdd42fe9501ee81185f67a4166a Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Jan 2008 00:54:17 -0500 Subject: fix timers so that they work when theres lots of repeating timers in the queue.. --- openbox/ping.c | 1 - 1 file changed, 1 deletion(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index d159805d..19922b25 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -108,7 +108,6 @@ static void ping_send(ObPingTarget *t) { t->sent = event_get_server_time(); /*ob_debug("PING: '%s' (timestamp %lu)\n", t->client->title, t->sent);*/ - ob_debug("PINGing client %s at %lu\n", t->client->title, t->sent); PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->sent, t->client->window, 0, 0, NoEventMask); -- cgit v1.2.3 From cafba3acf3ef5b34be867a155ec05b35e82384e9 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Jan 2008 01:16:47 -0500 Subject: active = FALSE when not active ! --- openbox/ping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 19922b25..d4217fdd 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -148,7 +148,7 @@ static void ping_end(ObClient *client, gpointer data) /* stop listening if we're not waiting for any more pings */ if (!ping_targets) { - active = TRUE; + active = FALSE; client_remove_destroy_notify(ping_end); } } -- cgit v1.2.3 From 0be98fee4743c795b06aa23881b82eff5bab3ef6 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Wed, 16 Jan 2008 15:25:08 +0100 Subject: Various fixes for sparse warnings. Define void functions with (void), not (). Add missing includes. Some functions were declared static but defined non-static. Some variables that should be file static were file global but not used in any other file. prop.h defined a new prop_atoms in each file that included it instead of declaring it extern. --- openbox/ping.c | 1 + 1 file changed, 1 insertion(+) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index d4217fdd..eed09479 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -21,6 +21,7 @@ #include "client.h" #include "prop.h" #include "event.h" +#include "debug.h" #include "mainloop.h" #include "openbox.h" -- cgit v1.2.3 From 2ee4251092a70af6a7c1826aaef01506dfcbf556 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Jan 2008 18:16:49 -0500 Subject: use unique IDs for pings rather than a timestamp. avoids duplicates. --- openbox/ping.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index eed09479..92fb8630 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -29,12 +29,13 @@ typedef struct _ObPingTarget { ObClient *client; ObPingEventHandler h; - Time sent; + guint32 id; gint waiting; } ObPingTarget; static GSList *ping_targets = NULL; static gboolean active = FALSE; +static guint32 ping_next_id = 1; #define PING_TIMEOUT (G_USEC_PER_SEC * 3) /*! Warn the user after this many PING_TIMEOUT intervals */ @@ -79,7 +80,7 @@ void ping_stop(struct _ObClient *c) ping_end(c, NULL); } -void ping_got_pong(Time timestamp) +void ping_got_pong(guint32 id) { GSList *it; ObPingTarget *t; @@ -87,9 +88,8 @@ void ping_got_pong(Time timestamp) /* make sure we're not already pinging it */ for (it = ping_targets; it != NULL; it = g_slist_next(it)) { t = it->data; - if (t->sent == timestamp) { - /*ob_debug("PONG: '%s' (timestamp %lu)\n", t->client->title, - t->sent);*/ + if (t->id == id) { + /*g_print("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ if (t->waiting > PING_TIMEOUT_WARN) { /* we had notified that they weren't responding, so now we need to notify that they are again */ @@ -101,16 +101,15 @@ void ping_got_pong(Time timestamp) } if (it == NULL) - ob_debug("Got PONG with timestamp %lu but not waiting for one\n", - timestamp); + ob_debug("Got PONG with id %u but not waiting for one\n", id); } static void ping_send(ObPingTarget *t) { - t->sent = event_get_server_time(); - /*ob_debug("PING: '%s' (timestamp %lu)\n", t->client->title, t->sent);*/ + t->id = ping_next_id++; + /*g_print("+PING: '%s' (id %u)\n", t->client->title, t->id);*/ PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, - prop_atoms.net_wm_ping, t->sent, t->client->window, 0, 0, + prop_atoms.net_wm_ping, t->id, t->client->window, 0, 0, NoEventMask); } -- cgit v1.2.3 From 299687110d478a4928932f72031c345b27a01840 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Jan 2008 18:44:22 -0500 Subject: use hash tables in ping.[ch] instead of a list. we're pinging every window, not just windows youre trying to close, so don't use datastructures that suck with lots of windows.. --- openbox/ping.c | 119 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 63 insertions(+), 56 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 92fb8630..065cb60a 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -33,46 +33,59 @@ typedef struct _ObPingTarget gint waiting; } ObPingTarget; -static GSList *ping_targets = NULL; -static gboolean active = FALSE; -static guint32 ping_next_id = 1; +static GHashTable *ping_targets = NULL; +static GHashTable *ping_ids = NULL; +static guint32 ping_next_id = 1; #define PING_TIMEOUT (G_USEC_PER_SEC * 3) /*! Warn the user after this many PING_TIMEOUT intervals */ #define PING_TIMEOUT_WARN 3 -static void ping_send(ObPingTarget *t); -static void ping_end(ObClient *client, gpointer data); +static void ping_send(ObPingTarget *t); +static void ping_end(ObClient *client, gpointer data); static gboolean ping_timeout(gpointer data); +void ping_startup(gboolean reconfigure) +{ + if (reconfigure) return; + + ping_targets = g_hash_table_new(g_direct_hash, g_int_equal); + ping_ids = g_hash_table_new(g_direct_hash, g_int_equal); + + /* listen for clients to disappear */ + client_add_destroy_notify(ping_end, NULL); +} + +void ping_shutdown(gboolean reconfigure) +{ + if (reconfigure) return; + + g_hash_table_unref(ping_targets); + g_hash_table_unref(ping_ids); + + client_remove_destroy_notify(ping_end); +} + void ping_start(struct _ObClient *client, ObPingEventHandler h) { - GSList *it; ObPingTarget *t; g_assert(client->ping == TRUE); /* make sure we're not already pinging it */ - for (it = ping_targets; it != NULL; it = g_slist_next(it)) { - t = it->data; - if (t->client == client) return; - } + g_assert(g_hash_table_lookup(ping_targets, &client) == NULL); - t = g_new(ObPingTarget, 1); + t = g_new0(ObPingTarget, 1); t->client = client; t->h = h; - t->waiting = 1; /* first wait for a reply */ - ping_send(t); - ping_targets = g_slist_prepend(ping_targets, t); + g_hash_table_insert(ping_targets, &t->client, t); + ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, t, g_direct_equal, NULL); - - if (!active) { - active = TRUE; - /* listen for the client to disappear */ - client_add_destroy_notify(ping_end, NULL); - } + /* act like we just timed out immediately, to start the pinging process + now instead of after the first delay */ + ping_timeout(t); } void ping_stop(struct _ObClient *c) @@ -82,31 +95,35 @@ void ping_stop(struct _ObClient *c) void ping_got_pong(guint32 id) { - GSList *it; ObPingTarget *t; - /* make sure we're not already pinging it */ - for (it = ping_targets; it != NULL; it = g_slist_next(it)) { - t = it->data; - if (t->id == id) { - /*g_print("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ - if (t->waiting > PING_TIMEOUT_WARN) { - /* we had notified that they weren't responding, so now we - need to notify that they are again */ - t->h(t->client, FALSE); - } - t->waiting = 0; /* not waiting for a reply anymore */ - break; + if ((t = g_hash_table_lookup(ping_ids, &id))) { + /*g_print("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ + if (t->waiting > PING_TIMEOUT_WARN) { + /* we had notified that they weren't responding, so now we + need to notify that they are again */ + t->h(t->client, FALSE); } + t->waiting = 0; /* not waiting for a reply anymore */ } - - if (it == NULL) + else ob_debug("Got PONG with id %u but not waiting for one\n", id); } static void ping_send(ObPingTarget *t) { - t->id = ping_next_id++; + /* t->id is 0 when it hasn't been assigned an id ever yet. + we can reuse ids when t->waiting == 0, because we won't be getting a + pong for that id in the future again. that way for apps that aren't + timing out we don't need to remove/add them from/to the hash table */ + if (t->id == 0 || t->waiting > 0) { + /* pick an id, and reinsert in the hash table with the new id */ + if (t->id) g_hash_table_remove(ping_ids, &t->id); + t->id = ping_next_id; + if (++ping_next_id == 0) ++ping_next_id; /* skip 0 on wraparound */ + g_hash_table_insert(ping_ids, &t->id, t); + } + /*g_print("+PING: '%s' (id %u)\n", t->client->title, t->id);*/ PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->id, t->client->window, 0, 0, @@ -117,11 +134,9 @@ static gboolean ping_timeout(gpointer data) { ObPingTarget *t = data; - if (t->waiting == 0) { /* got a reply already */ - /* send another ping to make sure it's still alive */ - ping_send(t); - } + ping_send(t); + /* if the client hasn't been responding then do something about it */ if (t->waiting == PING_TIMEOUT_WARN) t->h(t->client, TRUE); /* notify that the client isn't responding */ @@ -132,23 +147,15 @@ static gboolean ping_timeout(gpointer data) static void ping_end(ObClient *client, gpointer data) { - GSList *it; ObPingTarget *t; - for (it = ping_targets; it != NULL; it = g_slist_next(it)) { - t = it->data; - if (t->client == client) { - ping_targets = g_slist_remove_link(ping_targets, it); - ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, - FALSE); - g_free(t); - break; - } - } + t = g_hash_table_lookup(ping_targets, &client); + g_assert(t); + + g_hash_table_remove(ping_targets, &t->client); + g_hash_table_remove(ping_ids, &t->id); + + ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, FALSE); - /* stop listening if we're not waiting for any more pings */ - if (!ping_targets) { - active = FALSE; - client_remove_destroy_notify(ping_end); - } + g_free(t); } -- cgit v1.2.3 From 7630f660350bc39d0535a5aeb1da69ba25baf26b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Jan 2008 18:53:15 -0500 Subject: only 1 hash table is needed in ping.c --- openbox/ping.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 065cb60a..16f95adb 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -33,7 +33,6 @@ typedef struct _ObPingTarget gint waiting; } ObPingTarget; -static GHashTable *ping_targets = NULL; static GHashTable *ping_ids = NULL; static guint32 ping_next_id = 1; @@ -44,12 +43,12 @@ static guint32 ping_next_id = 1; static void ping_send(ObPingTarget *t); static void ping_end(ObClient *client, gpointer data); static gboolean ping_timeout(gpointer data); +static gboolean find_client(gpointer key, gpointer value, gpointer client); void ping_startup(gboolean reconfigure) { if (reconfigure) return; - ping_targets = g_hash_table_new(g_direct_hash, g_int_equal); ping_ids = g_hash_table_new(g_direct_hash, g_int_equal); /* listen for clients to disappear */ @@ -60,7 +59,6 @@ void ping_shutdown(gboolean reconfigure) { if (reconfigure) return; - g_hash_table_unref(ping_targets); g_hash_table_unref(ping_ids); client_remove_destroy_notify(ping_end); @@ -70,17 +68,14 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h) { ObPingTarget *t; - g_assert(client->ping == TRUE); + g_assert(g_hash_table_find(ping_ids, find_client, client) == NULL); - /* make sure we're not already pinging it */ - g_assert(g_hash_table_lookup(ping_targets, &client) == NULL); + g_assert(client->ping == TRUE); t = g_new0(ObPingTarget, 1); t->client = client; t->h = h; - g_hash_table_insert(ping_targets, &t->client, t); - ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, t, g_direct_equal, NULL); /* act like we just timed out immediately, to start the pinging process @@ -110,6 +105,12 @@ void ping_got_pong(guint32 id) ob_debug("Got PONG with id %u but not waiting for one\n", id); } +static gboolean find_client(gpointer key, gpointer value, gpointer client) +{ + ObPingTarget *t = value; + return t->client == client; +} + static void ping_send(ObPingTarget *t) { /* t->id is 0 when it hasn't been assigned an id ever yet. @@ -149,10 +150,9 @@ static void ping_end(ObClient *client, gpointer data) { ObPingTarget *t; - t = g_hash_table_lookup(ping_targets, &client); - g_assert(t); + t = g_hash_table_find(ping_ids, find_client, client); + g_assert (t != NULL); - g_hash_table_remove(ping_targets, &t->client); g_hash_table_remove(ping_ids, &t->id); ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, FALSE); -- cgit v1.2.3 From cccc57fdb04b2e5602254f1eb623acc95f9a032e Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Jan 2008 19:21:42 -0500 Subject: make the ping hash tables work correctly. don't need to stop pinging, it will automatically. and not all windows get pings, even tho we get notified that they are being destroyed --- openbox/ping.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'openbox/ping.c') diff --git a/openbox/ping.c b/openbox/ping.c index 16f95adb..37b5d30c 100644 --- a/openbox/ping.c +++ b/openbox/ping.c @@ -49,7 +49,7 @@ void ping_startup(gboolean reconfigure) { if (reconfigure) return; - ping_ids = g_hash_table_new(g_direct_hash, g_int_equal); + ping_ids = g_hash_table_new(g_int_hash, g_int_equal); /* listen for clients to disappear */ client_add_destroy_notify(ping_end, NULL); @@ -60,6 +60,7 @@ void ping_shutdown(gboolean reconfigure) if (reconfigure) return; g_hash_table_unref(ping_ids); + ping_ids = NULL; client_remove_destroy_notify(ping_end); } @@ -68,6 +69,7 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h) { ObPingTarget *t; + /* make sure we're not already pinging the client */ g_assert(g_hash_table_find(ping_ids, find_client, client) == NULL); g_assert(client->ping == TRUE); @@ -79,8 +81,12 @@ void ping_start(struct _ObClient *client, ObPingEventHandler h) ob_main_loop_timeout_add(ob_main_loop, PING_TIMEOUT, ping_timeout, t, g_direct_equal, NULL); /* act like we just timed out immediately, to start the pinging process - now instead of after the first delay */ + now instead of after the first delay. this makes sure the client + ends up in the ping_ids hash table now. */ ping_timeout(t); + + /* make sure we can remove the client later */ + g_assert(g_hash_table_find(ping_ids, find_client, client) != NULL); } void ping_stop(struct _ObClient *c) @@ -93,7 +99,7 @@ void ping_got_pong(guint32 id) ObPingTarget *t; if ((t = g_hash_table_lookup(ping_ids, &id))) { - /*g_print("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ + /*ob_debug("-PONG: '%s' (id %u)\n", t->client->title, t->id);*/ if (t->waiting > PING_TIMEOUT_WARN) { /* we had notified that they weren't responding, so now we need to notify that they are again */ @@ -125,7 +131,7 @@ static void ping_send(ObPingTarget *t) g_hash_table_insert(ping_ids, &t->id, t); } - /*g_print("+PING: '%s' (id %u)\n", t->client->title, t->id);*/ + /*ob_debug("+PING: '%s' (id %u)\n", t->client->title, t->id);*/ PROP_MSG_TO(t->client->window, t->client->window, wm_protocols, prop_atoms.net_wm_ping, t->id, t->client->window, 0, 0, NoEventMask); @@ -150,12 +156,11 @@ static void ping_end(ObClient *client, gpointer data) { ObPingTarget *t; - t = g_hash_table_find(ping_ids, find_client, client); - g_assert (t != NULL); - - g_hash_table_remove(ping_ids, &t->id); + if ((t = g_hash_table_find(ping_ids, find_client, client))) { + g_hash_table_remove(ping_ids, &t->id); - ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, FALSE); + ob_main_loop_timeout_remove_data(ob_main_loop, ping_timeout, t, FALSE); - g_free(t); + g_free(t); + } } -- cgit v1.2.3