Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-15133] Crash when deallocating a never-resumed DispatchSourceTimer #604

Closed
mickeyl opened this issue Aug 29, 2021 · 7 comments
Closed

Comments

@mickeyl
Copy link

mickeyl commented Aug 29, 2021

Previous ID SR-15133
Radar rdar://problem/82535083
Original Reporter @mickeyl
Type Bug
Environment

macOS 12 beta, Xcode 13 (13A233).

Additional Detail from JIRA
Votes 0
Component/s libdispatch
Labels Bug, DispatchSourceTimer
Assignee None
Priority Medium

md5: 61e077b082169a945b058843ee5c3245

Issue Description:

Please consider the following example program which I have uploaded to

https://github.com/mickeyl/swift-bugs/tree/main/SR15133

Running it from within Xcode crashes with the following backtrace:

(lldb) bt

I suspect there is a memory management problem when the stored continuation in the `StreamCommand` gets deallocated due to `self.activeCommand = nil` while the continuation may continue to run in another task.

@mickeyl
Copy link
Author

mickeyl commented Aug 29, 2021

It also crashes when running on the command line with `swift run`, btw.

@typesanitizer
Copy link

@swift-ci create

@mickeyl
Copy link
Author

mickeyl commented Sep 21, 2021

Same in Xcode 13 release version.

@mickeyl
Copy link
Author

mickeyl commented Sep 23, 2021

On Linux w/ Swift version 5.6-dev (LLVM ca88d53176e346a, Swift a382f589a5ec230), this seems to work.

It still fails on macOS 12 with Swift development toolchain 2021-09-18.

@mickeyl
Copy link
Author

mickeyl commented Sep 27, 2021

After digging deeper, it seems that the actual crash happens when deallocating the `DispatchTimerSource`. Obviously `libdispatch` is to blame here and it has nothing to do with the continuation. I will adjust the metadata accordingly.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from swiftlang/swift May 5, 2022
@Kyle-Ye
Copy link
Collaborator

Kyle-Ye commented Jul 24, 2024

I have encountered the bug in my codebase too.

And I can reproduce it stably with your great example code.

After some digging I can create a more simple reproductive code snippet.

// main.swift
import Foundation
import Dispatch

class Command {
    let timer: DispatchSourceTimer
    
    init() {
        self.timer = DispatchSource.makeTimerSource()
    }
}

func test() {
    var command: Command? = Command()
    command = nil
}

test()
dispatchMain()

Checking the libdispatch code

void
_dispatch_queue_xref_dispose(dispatch_queue_t dq)
{
uint64_t dq_state = os_atomic_load2o(dq, dq_state, relaxed);
if (unlikely(_dq_state_is_suspended(dq_state))) {
long state = (long)dq_state;
if (sizeof(long) < sizeof(uint64_t)) state = (long)(dq_state >> 32);
if (unlikely(_dq_state_is_inactive(dq_state))) {
// Arguments for and against this assert are within 6705399
DISPATCH_CLIENT_CRASH(state, "Release of an inactive object");
}
DISPATCH_CLIENT_CRASH(dq_state, "Release of a suspended object");
}
os_atomic_or2o(dq, dq_atomic_flags, DQF_RELEASED, relaxed);
}

The crash reason is that the object is in a inactive state.

It has nothing to do with timer.cancel, timer.setEventHandler nor timer.schedule.

It is because we create the object but dealloc it before calling timer.resume.

The solution is always calling activate/resume after you create the DispatchSourceTimer object.

class X {
    private var timer: DispatchSourceTimer!

    func y() {
        if timer == nil {
            timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global(qos: .userInteractive))
            timer.resume() // Or timer.activate()
        }
    }
}

@Kyle-Ye
Copy link
Collaborator

Kyle-Ye commented Jul 24, 2024

@mickeyl Did what I said above convince you? I think it's better to mark this issue as closed to better reflect the status here. cc @MadCoder as I do not have the corresponding permission on this repo.

@Kyle-Ye Kyle-Ye closed this as completed Jul 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants