Opened 8 years ago

Closed 8 years ago

#5106 closed Bug (duplicate)

Crash on Mac When Finishing Torrent Download, Seeding, and Removing At Same Time

Reported by: rammjet Owned by: livings124
Priority: Normal Milestone: None Set
Component: Mac Client Version: 2.73
Severity: Normal Keywords: crash Mac finish
Cc: transmission@…

Description

Sometime during finishing a download, moving the downloaded file to the final directory and removing the finished torrent, Transmission crashes. This has happened over several versions. No special messages appear in Console except that it crashed. Crash log: http://pastebin.com/Tf7RAJPw

Change History (47)

comment:1 Changed 8 years ago by jordan

  • Component changed from Transmission to Mac Client
  • Owner set to livings124

Contents of the pastebin:

Process:         Transmission [1160]
Path:            /Applications/Transmission.app/Contents/MacOS/Transmission
Identifier:      org.m0k.transmission
Version:         2.73 (13589)
Code Type:       X86-64 (Native)
Parent Process:  launchd [133]
User ID:         501
 
Date/Time:       2012-10-24 00:00:00.252 -0400
OS Version:      Mac OS X 10.8.2 (12C54)
Report Version:  10
 
Crashed Thread:  0  Dispatch queue: com.apple.main-thread
 
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000058
 
VM Regions Near 0x58:
-->
    __TEXT                 0000000100000000-00000001000f3000 [  972K] r-x/rwx SM=COW  /Applications/Transmission.app/Contents/MacOS/Transmission
 
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   org.m0k.transmission                0x00000001000244a0 0x100000000 + 148640
1   org.m0k.transmission                0x000000010002578f 0x100000000 + 153487
2   org.m0k.transmission                0x00000001000296d1 0x100000000 + 169681
3   org.m0k.transmission                0x0000000100023ff9 0x100000000 + 147449
4   org.m0k.transmission                0x00000001000094ed 0x100000000 + 38125
5   com.apple.AppKit                    0x00007fff8df87c62 -[_NSAnimationContextCompletionHandlerAgent dereference] + 120
6   com.apple.AppKit                    0x00007fff8dfb270d -[NSInFlightAnimation advanceToTime:] + 589
7   com.apple.AppKit                    0x00007fff8dfb1f77 -[NSAnimationManager animationTimerFired:] + 1093
8   com.apple.Foundation                0x00007fff89f31513 __NSFireTimer + 96
9   com.apple.CoreFoundation            0x00007fff8a7aada4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
10  com.apple.CoreFoundation            0x00007fff8a7aa8bd __CFRunLoopDoTimer + 557
11  com.apple.CoreFoundation            0x00007fff8a790099 __CFRunLoopRun + 1513
12  com.apple.CoreFoundation            0x00007fff8a78f6b2 CFRunLoopRunSpecific + 290
13  com.apple.HIToolbox                 0x00007fff907a70a4 RunCurrentEventLoopInMode + 209
14  com.apple.HIToolbox                 0x00007fff907a6e42 ReceiveNextEventCommon + 356
15  com.apple.HIToolbox                 0x00007fff907a6cd3 BlockUntilNextEventMatchingListInMode + 62
16  com.apple.AppKit                    0x00007fff8e036613 _DPSNextEvent + 685
17  com.apple.AppKit                    0x00007fff8e035ed2 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
18  com.apple.AppKit                    0x00007fff8e02d283 -[NSApplication run] + 517
19  com.apple.AppKit                    0x00007fff8dfd1cb6 NSApplicationMain + 869
20  org.m0k.transmission                0x0000000100002536 0x100000000 + 9526
21  org.m0k.transmission                0x0000000100002284 0x100000000 + 8836
 
Thread 1:: Dispatch queue: com.apple.libdispatch-manager
0   libsystem_kernel.dylib              0x00007fff9243fd16 kevent + 10
1   libdispatch.dylib                   0x00007fff8de28dea _dispatch_mgr_invoke + 883
2   libdispatch.dylib                   0x00007fff8de289ee _dispatch_mgr_thread + 54
 
Thread 2:
0   libsystem_kernel.dylib              0x00007fff9243fd16 kevent + 10
1   org.m0k.transmission                0x00000001000a4d1f 0x100000000 + 675103
2   org.m0k.transmission                0x000000010009bdd3 0x100000000 + 638419
3   org.m0k.transmission                0x000000010007168b 0x100000000 + 464523
4   org.m0k.transmission                0x0000000100067c80 0x100000000 + 425088
5   libsystem_c.dylib                   0x00007fff93b73742 _pthread_start + 327
6   libsystem_c.dylib                   0x00007fff93b60181 thread_start + 13
 
Thread 3:
0   libsystem_kernel.dylib              0x00007fff9243f322 __select + 10
1   org.m0k.transmission                0x0000000100083219 0x100000000 + 537113
2   org.m0k.transmission                0x0000000100067c80 0x100000000 + 425088
3   libsystem_c.dylib                   0x00007fff93b73742 _pthread_start + 327
4   libsystem_c.dylib                   0x00007fff93b60181 thread_start + 13
 
Thread 4:
0   libsystem_kernel.dylib              0x00007fff9243fd16 kevent + 10
1   org.m0k.transmission                0x0000000100032a61 0x100000000 + 207457
2   com.apple.Foundation                0x00007fff89f53612 __NSThread__main__ + 1345
3   libsystem_c.dylib                   0x00007fff93b73742 _pthread_start + 327
4   libsystem_c.dylib                   0x00007fff93b60181 thread_start + 13
 
Thread 5:: com.apple.CFSocket.private
0   libsystem_kernel.dylib              0x00007fff9243f322 __select + 10
1   com.apple.CoreFoundation            0x00007fff8a7cf4e6 __CFSocketManager + 1302
2   libsystem_c.dylib                   0x00007fff93b73742 _pthread_start + 327
3   libsystem_c.dylib                   0x00007fff93b60181 thread_start + 13
 
Thread 6:
0   libsystem_kernel.dylib              0x00007fff9243f6d6 __workq_kernreturn + 10
1   libsystem_c.dylib                   0x00007fff93b75eec _pthread_workq_return + 25
2   libsystem_c.dylib                   0x00007fff93b75cb3 _pthread_wqthread + 412
3   libsystem_c.dylib                   0x00007fff93b60171 start_wqthread + 13
 
Thread 7:
0   libsystem_kernel.dylib              0x00007fff9243f6d6 __workq_kernreturn + 10
1   libsystem_c.dylib                   0x00007fff93b75eec _pthread_workq_return + 25
2   libsystem_c.dylib                   0x00007fff93b75cb3 _pthread_wqthread + 412
3   libsystem_c.dylib                   0x00007fff93b60171 start_wqthread + 13
 
Thread 8:
0   libsystem_kernel.dylib              0x00007fff9243f6d6 __workq_kernreturn + 10
1   libsystem_c.dylib                   0x00007fff93b75eec _pthread_workq_return + 25
2   libsystem_c.dylib                   0x00007fff93b75cb3 _pthread_wqthread + 412
3   libsystem_c.dylib                   0x00007fff93b60171 start_wqthread + 13
 
Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x0000000106f094b0  rcx: 0x00007fff5fbfe130  rdx: 0x0000000000000000
  rdi: 0x000000010204f808  rsi: 0x00000001000b6bd5  rbp: 0x00007fff5fbfe0b0  rsp: 0x00007fff5fbfe0b0
   r8: 0x0000000000000010   r9: 0x00007fff5fbfdd20  r10: 0x00000001007f5740  r11: 0x00000001008aa970
  r12: 0x0000000000000000  r13: 0x0000000101340e50  r14: 0x0000000106f094b0  r15: 0x0000000000000001
  rip: 0x00000001000244a0  rfl: 0x0000000000010246  cr2: 0x0000000000000058
Logical CPU: 1}}}

comment:2 Changed 8 years ago by livings124

Could you post a crash log from a version from https://build.transmissionbt.com/job/trunk-mac/?

comment:3 Changed 8 years ago by rammjet

OK, from Trunk Build #5409, version 2.73 (13594) - http://pastebin.com/A9MFUKh4

comment:4 Changed 8 years ago by livings124

How is the transfer being removed? Is it automatic? Did you finish seeding as well as downloading?

comment:5 Changed 8 years ago by rammjet

Yes, the removal is automatic after downloading and finish seeding and then crashing. It is not necessarily the last torrent that crashes, there may be others in process. The crash is intermittent - it does not happen on every torrent but maybe 1 out of 3 or 5.

comment:6 Changed 8 years ago by x190

Controller.m Line 1604 in - (void) clearCompleted: (id) sender

-[torrents release];
+[torrents autorelease];

Might do the trick?

comment:7 Changed 8 years ago by livings124

x190: I do not understand how that would fix this issue.

comment:8 Changed 8 years ago by x190

From the CR we see - (void) drawInteriorWithFrame: (NSRect) cellFrame inView: (NSView *) controlView being called...

- (void) drawInteriorWithFrame: (NSRect) cellFrame inView: (NSView *) controlView
{
    Torrent * torrent = [self representedObject];
    NSAssert(torrent != nil, @"can't have a TorrentCell without a Torrent");

...and as you see "NSAssert(torrent != nil, @"can't have a TorrentCell? without a Torrent");", so I'm guessing there might be a timing issue here that autorelease would resolve.

comment:9 Changed 8 years ago by livings124

r13603 has an experimental fix for this. rammjet, could you test it from https://build.transmissionbt.com/job/trunk-mac/?

comment:10 Changed 8 years ago by rammjet

Sorry it crashed again.

Transmission #5414, 2.73+ (13603)

Crash log: http://pastebin.com/pm41wS1p

comment:11 Changed 8 years ago by x190

This crash occurs in Line 641 of TorrentCell?.m according to the CR.

   //unwanted section
    if (!NSIsEmptyRect(missingRect))
    {
        if (![torrent isMagnet])
            [[ProgressGradients progressLightGrayGradient] drawInRect: missingRect angle: 90];
        else
            [[ProgressGradients progressRedGradient] drawInRect: missingRect angle: 90];
    }
}

rammjet: Is it possible a new torrent was being added when this crash occurred or was the auto-removal the only activity at the time of the crash?

comment:12 Changed 8 years ago by rammjet

I'm pretty sure it wasn't during adding a torrent. I add them manually through magnet links and it took them just fine. I didn't sit and watch the process to see if it actually happened on removal. I let it run. Some torrents finished without incident. Then I discovered it to have crashed. I did not see the actual crash. I can't force it to crash. I just have to add a bunch of links and wait for one of them to crash when it finishes which could be any uncertain time.

comment:13 Changed 8 years ago by x190

Okay, I think I got it. This fancy animation thingy is firing off, but "isMagnet" is invalid address space as libtransmission has already freed its return value.

Easy fix: Ditch animation thingy. :) [[NSAnimationContext currentContext] setDuration: 0];

Last edited 8 years ago by x190 (previous) (diff)

comment:14 Changed 8 years ago by rammjet

I don't know when you added the "animation thingy", but I have v2.61 labelled as crashing.

Further info: when I noticed that it was crashing regularly, I deleted all Transmission files except ones that set the config, and let Transmission create them again. This did not help. Also, I add the magnet links through the web interface and that interface is running all the time.

comment:15 Changed 8 years ago by livings124

I don't see how it would fix this, but r13608 does clean up some of the messy retain/release code. Any difference?

Last edited 8 years ago by livings124 (previous) (diff)

comment:16 Changed 8 years ago by x190

livings124: Controller.m Line 1495--if (!beganUpdate). If this test fails, animation will still occur as it is outside that code block, however, the torrents will hit closeRemoveTorrent at Line 1537 because !beganUpdate will now be true at that point. So you are likely removing the torrent while animation is still occurring, in that case.

You could move the animation code inside the completion handler code block.

comment:17 Changed 8 years ago by livings124

x190: I do not understand. !beganUpdate will only be true once (since when it's hit the first time, beganUpdate is set to YES). So if that test fails at 1495, it will have to fail at 1537.

comment:18 Changed 8 years ago by cfpp2p

beganUpdate = NO initialized at line 1484

only other place beganUpdate changed is line 1506 beganUpdate = YES and inside code ONLY when beganUpdate = NO

as livings124 said

!beganUpdate will only be true once (since when it's hit the first time, beganUpdate is set to YES)

The code at line 1533

    if (!beganUpdate)
    {
        //do here if we're not doing it at the end of the animation
        for (Torrent * torrent in torrents)
            [torrent closeRemoveTorrent: deleteData];
    }

looks to me like it will NEVER be executed. This can't possibly be correct/must be DEAD code.

This all began with r13132 #4696.

I don't know the Mac code. There seems to be problems with this section of code whether or not the crash problem stems from it.

These are my observations. Since I don't know the Mac code if you guys want me to keep my nose out of it, I will... LOL

update:

line 1493 if ([NSApp isOnLionOrBetter])

in this case

beganUpdate = YES will never happen and WILL allow code inside line 1533 to be executed, whatever that may do/crash.

Last edited 8 years ago by cfpp2p (previous) (diff)

comment:19 Changed 8 years ago by livings124

Line 1533 will be executed if there are no displayed torrents. Notice the code at line 1486 is a block, meaning we're not calling it until line 1521 or 1524.

comment:20 Changed 8 years ago by cfpp2p

hmmm?? OK, I'll try to get my head around this after I let my brain flush out a little.

comment:21 Changed 8 years ago by x190

Repeating comment:15, so that rammjet will see it. :)

"I don't see how it would fix this, but r13608 does clean up some of the messy retain/release code. Any difference?"

Last edited 8 years ago by x190 (previous) (diff)

comment:22 Changed 8 years ago by rammjet

OK, r13608 crashed: http://pastebin.com/351r85pC

I had 4 torrents. 2 were seeding. 1 was seconds from finishing downloading. The one that corresponds to the crash had just finished seeding and was being removed from the torrent list.

comment:23 Changed 8 years ago by rammjet

Sorry, didn't catch what you were trying to tell me. I have now downloaded r13608 and will start testing it.

comment:24 Changed 8 years ago by x190

Simultaneous "downloadComplete/seedingComplete/Remove from the transfer list when seeding completes" triggers the following crash on 10.8.2.


https://forum.transmissionbt.com/viewtopic.php?f=2&t=14093&p=62608#p62597 (Same crash---see ticket summary).

Note: [_NSAnimationContextCompletionHandlerAgent dereference] + 120 is being done before animation is complete.

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 org.m0k.transmission 0x00000001000244a0 0x100000000 + 148640
1 org.m0k.transmission 0x000000010002578f 0x100000000 + 153487
2 org.m0k.transmission 0x00000001000296d1 0x100000000 + 169681
3 org.m0k.transmission 0x0000000100023ff9 0x100000000 + 147449
4 org.m0k.transmission 0x00000001000094ed 0x100000000 + 38125
5 com.apple.AppKit 0x00007fff86718c62 -[_NSAnimationContextCompletionHandlerAgent dereference] + 120
6 com.apple.AppKit 0x00007fff8674370d -[NSInFlightAnimation advanceToTime:] + 589
7 com.apple.AppKit 0x00007fff86742f77 -[NSAnimationManager animationTimerFired:] + 1093
8 com.apple.Foundation 0x00007fff8a542513 __NSFireTimer + 96
9 com.apple.CoreFoundation 0x00007fff824acda4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 20
10 com.apple.CoreFoundation 0x00007fff824ac8bd __CFRunLoopDoTimer + 557
11 com.apple.CoreFoundation 0x00007fff82492099 __CFRunLoopRun + 1513

Thread 4:
0 libsystem_kernel.dylib 0x00007fff8ac500fa __psynch_cvwait + 10
1 libsystem_c.dylib 0x00007fff81d96f89 _pthread_cond_wait + 869
2 com.apple.Foundation 0x00007fff8a562cc6 -[NSCondition wait] + 240
3 com.apple.Foundation 0x00007fff8a55b468 -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 796
4 com.apple.Foundation 0x00007fff8a55b0c8 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:] + 131
5 org.m0k.transmission 0x000000010003318d 0x100000000 + 209293
6 com.apple.CoreFoundation 0x00007fff824de737 ___forwarding___ + 775
7 com.apple.CoreFoundation 0x00007fff824de3b8 _CF_forwarding_prep_0 + 232
8 org.m0k.transmission 0x0000000100032c67 0x100000000 + 207975
9 org.m0k.transmission 0x0000000100032b8f 0x100000000 + 207759
10 com.apple.Foundation 0x00007fff8a564612 __NSThread__main__ + 1345
11 libsystem_c.dylib 0x00007fff81d92742 _pthread_start + 327
12 libsystem_c.dylib 0x00007fff81d7f181 thread_start + 13
Last edited 8 years ago by x190 (previous) (diff)

comment:25 Changed 8 years ago by x190

Simultaneous "downloadComplete/seedingComplete/Remove from the transfer list when seeding completes" triggers the following crash on 10.6.8.


https://forum.transmissionbt.com/viewtopic.php?f=4&t=14106&sid=f040e21b40bb60b37b7a0d70dda12e25

Application Specific Information:
Assertion failed: (tr_isTorrent( tor )), function tr_torrentStat, file /Users/transmission/hudson/workspace/trunk-mac/trunk/libtransmission/torrent.c, line 1188.
 

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libSystem.B.dylib             	0x00007fff81b890b6 __kill + 10
1   libSystem.B.dylib             	0x00007fff81c299f6 abort + 83
2   libSystem.B.dylib             	0x00007fff81c169bc __pthread_markcancel + 0
3   org.m0k.transmission          	0x000000010006bd87 tr_torrentStat + 1720
4   org.m0k.transmission          	0x00000001000294be -[Torrent(Private) completenessChange:] + 43
5   com.apple.Foundation          	0x00007fff854f245f __NSThreadPerformPerform + 219
6   com.apple.CoreFoundation      	0x00007fff81de73d1 __CFRunLoopDoSources0 + 1361
7   com.apple.CoreFoundation      	0x00007fff81de55c9 __CFRunLoopRun + 873
8   com.apple.CoreFoundation      	0x00007fff81de4d8f CFRunLoopRunSpecific + 575
9   com.apple.HIToolbox           	0x00007fff8a4f27ee RunCurrentEventLoopInMode + 333
10  com.apple.HIToolbox           	0x00007fff8a4f25f3 ReceiveNextEventCommon + 310
11  com.apple.HIToolbox           	0x00007fff8a4f24ac BlockUntilNextEventMatchingListInMode + 59
12  com.apple.AppKit              	0x00007fff83a96eb2 _DPSNextEvent + 708
13  com.apple.AppKit              	0x00007fff83a96801 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155
14  com.apple.AppKit              	0x00007fff83a5c68f -[NSApplication run] + 395
15  com.apple.AppKit              	0x00007fff83a553b0 NSApplicationMain + 364
16  org.m0k.transmission          	0x0000000100001926 main + 111
17  org.m0k.transmission          	0x0000000100001674 start + 52

Last edited 8 years ago by x190 (previous) (diff)

comment:26 Changed 8 years ago by x190

Version: 2.73 + (13620): (10.8.2 Animation crash):

https://forum.transmissionbt.com/viewtopic.php?f=2&t=14093#p62637

comment:27 Changed 8 years ago by fsw

  • Cc transmission@… added

comment:28 Changed 8 years ago by livings124

  • Summary changed from Crash on Mac When Finishing Torrent Download to Crash on Mac When Finishing Torrent Download, Seeding, and Removing At Same Time

comment:29 Changed 8 years ago by livings124

  • Component changed from Mac Client to Transmission
  • Owner changed from livings124 to jordan

There is a bug in Transmission where the ratio or idle limit callbacks are called twice. I have a change to the Mac client that works around this bug, but I'd prefer it to be fixed in libtransmission.

comment:30 Changed 8 years ago by livings124

  • Owner changed from jordan to livings124

r13622 fixes this by working around #5146.

comment:31 Changed 8 years ago by livings124

  • Component changed from Transmission to Mac Client
  • Milestone changed from None Set to 2.80
  • Resolution set to fixed
  • Status changed from new to closed

comment:32 Changed 8 years ago by x190

  • Resolution fixed deleted
  • Status changed from closed to reopened

comment:33 Changed 8 years ago by x190

Simultaneous "downloadComplete/seedingComplete/Remove from the transfer list when seeding completes" triggers the following crash on 10.6.8.

Version: 2.73 + (13622): OS Version: Mac OS X 10.6.8 (10K549):

Application Specific Information: Assertion failed: (tr_isTorrent( tor )), function tr_torrentStat, file /Users/transmission/hudson/workspace/trunk-mac/trunk/libtransmission/torrent.c, line 1188.

Thread 0 Crashed:  Dispatch queue: com.apple.main-thread
0   libSystem.B.dylib             	0x00007fff81b890b6 __kill + 10
1   libSystem.B.dylib             	0x00007fff81c299f6 abort + 83
2   libSystem.B.dylib             	0x00007fff81c169bc __pthread_markcancel + 0
3   org.m0k.transmission          	0x000000010006bc77 tr_torrentStat + 1720
4   org.m0k.transmission          	0x00000001000293ae -[Torrent(Private) completenessChange:] + 43
5   com.apple.Foundation          	0x00007fff854f245f __NSThreadPerformPerform + 219
6   com.apple.CoreFoundation      	0x00007fff81de73d1 __CFRunLoopDoSources0 + 1361
7   com.apple.CoreFoundation      	0x00007fff81de55c9 __CFRunLoopRun + 873
8   com.apple.CoreFoundation      	0x00007fff81de4d8f CFRunLoopRunSpecific + 575
9   com.apple.HIToolbox           	0x00007fff8a4f27ee RunCurrentEventLoopInMode + 333
10  com.apple.HIToolbox           	0x00007fff8a4f25f3 ReceiveNextEventCommon + 310
11  com.apple.HIToolbox           	0x00007fff8a4f24ac BlockUntilNextEventMatchingListInMode + 59
12  com.apple.AppKit              	0x00007fff83a96eb2 _DPSNextEvent + 708
13  com.apple.AppKit              	0x00007fff83a96801 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 155
14  com.apple.AppKit              	0x00007fff83a5c68f -[NSApplication run] + 395
15  com.apple.AppKit              	0x00007fff83a553b0 NSApplicationMain + 364
16  org.m0k.transmission          	0x0000000100001686 main + 111
17  org.m0k.transmission          	0x00000001000013d4 start + 52

Last edited 8 years ago by x190 (previous) (diff)

comment:34 Changed 8 years ago by cfpp2p

in this section of code of Torrent.m line 1644

    tr_torrentSetQueueStartCallback(fHandle, startQueueCallback, self);
    tr_torrentSetCompletenessCallback(fHandle, completenessChangeCallback, self);
    tr_torrentSetRatioLimitHitCallback(fHandle, ratioLimitHitCallback, self);
    tr_torrentSetIdleLimitHitCallback(fHandle, idleLimitHitCallback, self);
    tr_torrentSetMetadataCallback(fHandle, metadataCallback, self);

could it be that after ratioLimitHitCallback the Remove from the transfer list when seeding completes has now taken place so that when idleLimitHitCallback

void idleLimitHitCallback(tr_torrent * torrent, void * torrentData)
{
    [(Torrent *)torrentData performSelectorOnMainThread: @selector(idleLimitHit) withObject: nil waitUntilDone: NO];
}
}

calls idleLimitHit

Torrent.m line 1854

- (void) idleLimitHit
{
    fStat = tr_torrentStat(fHandle);
    
    [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentFinishedSeeding" object: self];
}

the calling of tr_torrentStat(fHandle) is on a non-existant torrent (Assertion failed: (tr_isTorrent( tor ) torrent.c, line 1188 since the torrent has now been removed from the list.

if tr_torrentSetRatioLimitHitCallback(fHandle, ratioLimitHitCallback, self); is what triggers Remove from the transfer list when seeding completes it seems like we need to break out of this section of code after tr_torrentSetRatioLimitHitCallback when Remove from the transfer list when seeding completes is enacted(true) because the torrent has now been removed from the transfer list.

is this on the correct track?

comment:35 Changed 8 years ago by x190

=========================================================================== Seems we have a race between the main thread (interface updates) and the event thread (torrent removal) and the event thread is winning, so in Controller.m:

2083	    if ([torrent removeWhenFinishSeeding])
2084            {
2085                sleep(1); //the interface has to update before we remove torrents
2086	            [self confirmRemoveTorrents: @[ torrent ] deleteData: NO];
2087            }
            else
            ...


===========================================================================

I don't have 'idle-seeding-limit' set. On 10.6.8 the crash occurs in - (void) completenessChange: (NSDictionary *) statusInfo because tr_torrentStat() fails its assert for tr_isTorrent(tor). There is no crash unless 'removeWhenFinishSeeding' is set.

Last edited 8 years ago by x190 (previous) (diff)

comment:36 Changed 8 years ago by livings124

cfpp2p: it's possible that #5146 is still causing the crash - the callback is called twice, but the torrent is deallocated after the first callback. Could you check if the code is trying to call it twice? Also, what order are the seeding and downloading callbacks called.

comment:37 Changed 8 years ago by cfpp2p

cfpp2p: it's possible that #5146 is still causing the crash - the callback is called twice, but the torrent is deallocated after the first callback. Could you check if the code is trying to call it twice? Also, what order are the seeding and downloading callbacks called.

I'm not sure where to post this information here or #5146

the callback is called twice but the torrent is deallocated after the first callback

tr_torrentCheckSeedLimit() does not deallocate anything it just stops torrents and leaves them in the list.

from tr_torrentCheckSeedLimit() --- if( tr_torrentIsSeedRatioDone( tor ) plus else if( tr_torrentIsSeedIdleLimitDone( tor ) ) both just set tor->isStopping = true, nothing is deallocated. tr_torrentStat() Assertion failed: (tr_isTorrent( tor ) torrent.c, line 1188 doesn't/can't happen through libtransmision this way and we aren't seeing crashes outside of Mac code like this.

the only place that I know of libtransmission allows deallocation is tr_torrentRemove() via RPC ( rpcimpl.c torrentRemove() ), nowhere else. There is no setting for torrentRemove_when_seeding_complete from libtransmission that I know of.

However Torrent.m has closeRemoveTorrent calling tr_torrentRemove() directly. Controller.m calls closeRemoveTorrent in five different places and this is where I think something might be awry.

Could you check if the code is trying to call it twice? Also, what order are the seeding and downloading callbacks called

I'll look into the code in more detail sometime next week, but hopefully you'll have all of this sorted out by then.

Last edited 8 years ago by cfpp2p (previous) (diff)

comment:38 Changed 8 years ago by livings124

tr_torrentCheckSeedLimit doesn't deallocate anything, but the callback in the Mac client will if set to remove when seeding completes. It's a potential bug when the 3 callbacks are called near-instantaneously when a torrent finishes downloading and seeding at once: seeding callback, then download callback, then seeding callback again. The seeding callback can remove the transfer, causing the other callbacks to hit the assert.

comment:39 Changed 8 years ago by x190

void
tr_torrentRecheckCompleteness( tr_torrent * tor )
{
    tr_completeness completeness;

    assert( tr_isTorrent( tor ) );

    tr_torrentLock( tor );
...

                /* if completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
          --->>>tr_torrentCheckSeedLimit( tor );
            }

 ...
            if( tr_sessionIsTorrentDoneScriptEnabled( tor->session ) )
                torrentCallScript( tor, tr_sessionGetTorrentDoneScript( tor->session ) );
        }

  --->>>fireCompletenessChange( tor, completeness, wasRunning );

        tr_torrentSetDirty( tor );
    }

    tr_torrentUnlock( tor );
}


Growl would appear to confirm that "Seeding Complete" fires first.

Last edited 8 years ago by x190 (previous) (diff)

comment:40 Changed 8 years ago by rammjet

Just to let you know, 13622 seems to have solved my problem. Ran several sessions over the weekend and no crashes. Hope you squash the remaining bugs.

comment:41 Changed 8 years ago by cfpp2p

First of all transmission is not real time interrupt driven processing so there isn't any simultaneous anything. One function's processing can take place immediately after another's but it is all linear processing, nothing simultaneously.

So near-instantaneously is the correct term.

Before I were to continue investigating this would someone please test code as per the following (or similar). I'm still convinced the problem is as described in my comment:34 If I'm incorrect on this, the following patched code will prove it to me and I'll be able to focus on some of the other ideas presented. I'm not a Mac programmer and don't pretend to be so. Correct the syntax as needed please, but the logic is to exit this section of code if the torrent has been deallocated by completenessChangeCallback.

Torrent.m

...

// needed for tr_isTorrent()
#import "torrent.h" // ?? how do we do this in Mac since import Torrent.h (with capitol T) is already listed?

...

- (BOOL) isTorrent
{
    return tr_isTorrent(fHandle);
}

...

//begin at line 1644

    tr_torrentSetQueueStartCallback(fHandle, startQueueCallback, self);
    tr_torrentSetCompletenessCallback(fHandle, completenessChangeCallback, self);

    /* if completenessChangeCallback has Removed torrent from the transfer list when seeding completes
       the torrent has been deallocated so there is no longer the torrent! */
    if (![self isTorrent])
        {
            /* assumes  Removed torrent from the transfer list when seeding completes
			has properly performed a release */
            return nil;
        }
    tr_torrentSetRatioLimitHitCallback(fHandle, ratioLimitHitCallback, self);
    tr_torrentSetIdleLimitHitCallback(fHandle, idleLimitHitCallback, self);
    tr_torrentSetMetadataCallback(fHandle, metadataCallback, self);

...
Last edited 8 years ago by cfpp2p (previous) (diff)

comment:42 Changed 8 years ago by x190

It appears that r13622 (fix issue caused by double "Seeding Complete" notifications) has fixed the animation crash on 10.8. Ref: https://trac.transmissionbt.com/ticket/5106#comment:40

Now we need to fix the ordering problem for 10.6. fireCompletenessChange(), which is for "Download Complete" notification, should be called before tr_torrentCheckSeedLimit() which fires the "Seeding Complete" notification and triggers torrent removal causing a crash in - (void) completenessChange: (NSDictionary *) statusInfo;[Torrent.m] because it fails an assert.

comment:43 Changed 8 years ago by cfpp2p

Now we need to fix the ordering problem for 10.6. fireCompletenessChange(), which is for "Download Complete" notification, should be called before tr_torrentCheckSeedLimit() which fires the "Seeding Complete" notification and triggers torrent removal causing a crash in - (void) completenessChange: (NSDictionary *) statusInfo;[Torrent.m] because it fails an assert.

This is what comment:41 is for, to fix the assertion failed that is documented. Please test.

tr_torrentStat() is nowhere in the path of fireCompletenessChange()

the call to tr_torrentStat() and resulting:

Assertion failed: (tr_isTorrent( tor )), function tr_torrentStat

is from:

Torrent.m line 1854

- (void) idleLimitHit
{
    fStat = tr_torrentStat(fHandle);
    
    [[NSNotificationCenter defaultCenter] postNotificationName: @"TorrentFinishedSeeding" object: self];
}

which causes the assert. Prove me wrong by testing the patch and we can go on. I'd do it myself but I don't have a Mac.

Last edited 8 years ago by cfpp2p (previous) (diff)

comment:45 Changed 8 years ago by livings124

If anyone can get breakpoints working, can you supply backtraces from where the three callbacks are called?

comment:47 Changed 8 years ago by livings124

  • Milestone changed from 2.80 to None Set
  • Resolution set to duplicate
  • Status changed from reopened to closed

#5146 is fixed. I'm tempted to mark this as fixed for 2.80 as a separate issue, but it probably makes more sense to close as a duplicate.

Note: See TracTickets for help on using tickets.