im.pidgin.pidgin: d77adf1b9a4b44f121620f20e2643602e3f6776e
Evan Schoenberg
evands at pidgin.im
Wed Jan 23 06:39:57 EST 2008
(Apologies to Mark for receiving this twice - this is the reply to
which Mark just replied).
On Jan 21, 2008, at 2:09 AM, Mark Doliner wrote:
> I disapproved this. I guess there are two reasons:
>
> 1. Checking the validity of a FlapConnection by checking whether the
> memory
> address of the struct exists in a GList is ugly. I imagine it will
> work
> 99.99999999% of the time, but it is theoretically possible for the
> same memory
> address to be reused for a new and different FlapConnection, which
> means you
> would end up free'ing something you hadn't intended.
I don't think that's right.
1. Every time a FlapConnection is made, it is immediately added to the
GList. There is only one entry point for creating a FlapConnection,
flap_connection_new()
2. Every time a FlapConnection is destroyed, it is immediately removed
from the GList. There is only one entry point for destroying a
FlapConnection, flap_connection_destroy_cb().
3. The same memory could certainly be used for a new FlapConnection
which was at some point in the past used for a FlapConnection, but
that's not relevant to this code. That could never happen while a
FlapConnection is valid (has not yet been freed) -- which is to say
that a FlapConnection could never be created which makes use of memory
currently pointed-to by the flap+connections list.
4. The list is used to check validity to ensure that a double-free
doesn't occur; at no point is it iterated and universally freed (which
would still never fail since the only way a FlapConnection is freed
will remove that pointer from the list at the same time).
Did I miss something?
Yes, it's ugly. The same sad-but-necessary technique is used to check
for PurpleConnection objects' validities, for the same reason: If a
callback is registered and is not canceled when the object is freed,
once it is called, we will crash. GObjectification of the objects in
question (with reference counting) -- or implementation of manual
reference counting -- would fix the problem.
> 2. This totally should not be necessary. If the FlapConnection is
> destroyed
> by flap_connection_destroy before the timeout is called then the
> timeout is
> removed. See the first two lines of flap_connection_destroy().
I see that, and I saw that. Nevertheless, I have the following back
trace, from libpurple 2.3.1 in Adium 1.2:
-----
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000c23eab8b
Crashed Thread: 0
Thread 0 Crashed:
0 libpurple 0x08a0cf4d
flap_connection_destroy_cb + 31
1 com.adiumX.AdiumPurple 0x08773d8c callTimerFunc + 25
2 com.apple.CoreFoundation 0x96018b7e CFRunLoopRunSpecific +
4494
3 com.apple.CoreFoundation 0x96018d38 CFRunLoopRunInMode + 88
4 com.apple.HIToolbox 0x931638a4
RunCurrentEventLoopInMode + 283
5 com.apple.HIToolbox 0x931636bd ReceiveNextEventCommon +
374
6 com.apple.HIToolbox 0x93163531
BlockUntilNextEventMatchingListInMode + 106
7 com.apple.AppKit 0x964fdd5b _DPSNextEvent + 657
8 com.apple.AppKit 0x964fd6a0 -[NSApplication
nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
9 com.apple.AppKit 0x964f66d1 -[NSApplication run] + 795
10 com.apple.AppKit 0x964c39ba NSApplicationMain + 574
11 com.adiumX.adiumX 0x00002fc2 _start + 216
12 com.adiumX.adiumX 0x00002ee9 start + 41
----
disassembly of the compiled libpurple 2.3.1 binary shipping with Adium
1.2 shows that flap_connection_destroy_cb + 31 is:
_flap_connection_destroy_cb:
+0 00100f2a 55 pushl %ebp
+1 00100f2b 89e5 movl %esp,%ebp
+3 00100f2d 56 pushl %esi
+4 00100f2e 53 pushl %ebx
+5 00100f2f 83ec50 subl $0x50,%esp
+8 00100f32 e800000000 calll 0x00100f37
+13 00100f37 5b popl %ebx
+14 00100f38 8b4508 movl 0x08(%ebp),%eax
+17 00100f3b 8945dc movl %eax,0xdc(%ebp)
+20 00100f3e 8b45dc movl 0xdc(%ebp),%eax
+23 00100f41 8b00 movl (%eax),%eax
+25 00100f43 8945e0 movl %eax,0xe0(%ebp)
+28 00100f46 8b45e0 movl 0xe0(%ebp),%eax
+31 00100f49 8bb0c8000000 movl 0x000000c8(%eax),%esi
+37 00100f4f e8eac1f1ff calll _purple_connections_get_all
+42 00100f54 89742404 movl %esi,0x04(%esp)
+46 00100f58 890424 movl %eax,(%esp)
+49 00100f5b e8d9b40d00 calll 0x001dc439 _g_list_find
Note that +37, _purple_connections_get_all, is the function call made
by PURPLE_CONNECTION_IS_VALID(). We crash before that. The only thing
which happens before that call is made is:
od = conn->od;
so dereferencing conn is causing a crash.
The explanation that came with the crash was, as is typical for
crashes in callback methods (there are several others which are
longtime offenders), "I woke my computer from sleep, and Adium crashed."
> For the record I absolutely hate PURPLE_CONNECTION_IS_VALID and
> think we
> should get rid of it.
Getting rid of it without a replacement would be crashtastic. I agree
that it's a hack of a solution which only catches those cases we have
the foresight to consider, and I'd love to see it replaced by an
actual solution. I've held off for a long time now on giving it
reference counting, as each time I return to consider doing so the
GObjectification discussion comes back... and GObjectification would
of course obsolete any such solution.
Cheers,
Evan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://pidgin.im/pipermail/devel/attachments/20080123/ee6d4cba/attachment.html>
More information about the Devel
mailing list