# HG changeset patch # User Evan Schoenberg # Date 1175393826 0 # Node ID a6a79b8616bfe9dc7683ff2a7a2640718db3157d # Parent 328ae2c041c36e37aa289265bf34dc9fc478ff26 I commonly see a crash in which socket_ready_cb(), shortly after a laptop wakes from sleep, is passed invalid (previously freed) connect_data. It looks like this: Thread 0 Crashed: 0 libobjc.A.dylib 0x90a59380 objc_msgSend 16 1 Libgaim 0x0fe23bcd gaim_proxy_connect_data_disconnect 172 2 Libgaim 0x0fe23d63 socket_ready_cb 199 3 com.apple.CoreFoundation 0x90843ffd __CFSocketDoCallback 551 (objc_msgSend is how ObjC routes messages... it's being called because connect_data->cconnect_cb is invalid). It appears that when this crash happens, the socket is marked as ready just before the computer sleeps; on the next run loop, the callback will be called [socket_ready_cb()]. The computer sleeps and every account is disconnected first, which calls gaim_proxy_connect_cancel_with_handle(), destroying the connect_data. When it awakens, it calls socket_ready_cb() and the crash occurs. I've added PURPLE_PROXY_CONNECT_DATA_IS_VALID, which takes advantage of the fact that all valid connect_data objects are stored in the handles GSList, just as PURPLE_GAIM_CONNECTION_IS_VALID works. diff -r 328ae2c041c3 -r a6a79b8616bf libpurple/proxy.c --- a/libpurple/proxy.c Sat Mar 31 21:48:11 2007 +0000 +++ b/libpurple/proxy.c Sun Apr 01 02:17:06 2007 +0000 @@ -87,6 +87,12 @@ static void try_connect(PurpleProxyConnectData *connect_data); +/* + * TODO: Eventually (GObjectification) this bad boy will be removed, because it is + * a gross fix for a crashy problem. + */ +#define PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data) g_slist_find(handles, connect_data) + /************************************************************************** * Proxy structure API **************************************************************************/ @@ -389,6 +395,12 @@ int error = 0; int ret; + /* If the socket-connected message had already been triggered when connect_data + * was destroyed via purple_proxy_connect_cancel(), we may get here with a freed connect_data. + */ + if (!PURPLE_PROXY_CONNECT_DATA_IS_VALID(connect_data)) + return; + purple_debug_info("proxy", "Connected to %s:%d.\n", connect_data->host, connect_data->port);