MailCore / mailcore2

MailCore 2 provide a simple and asynchronous API to work with e-mail protocols IMAP, POP and SMTP. The API has been redesigned from ground up.
Other
2.61k stars 627 forks source link

MCIMAPAsyncConnection EXC_BAD_ACCESS #1572

Open rlaferla opened 7 years ago

rlaferla commented 7 years ago

I'm seeing this spurious crash on iOS:

* thread #16: tid = 0xc0252, 0x0000000100301df4 Mailable`mailcore::IMAPAsyncConnection::dispatchQueue(this=0x0000000125e0cc60) + 28 at MCIMAPAsyncConnection.cpp:427, queue = 'mydispatchqueue', stop reason = EXC_BAD_ACCESS (code=1, address=0x1a19eb26d09)
  * frame #0: 0x0000000100301df4 Mailable`mailcore::IMAPAsyncConnection::dispatchQueue(this=0x0000000125e0cc60) + 28 at MCIMAPAsyncConnection.cpp:427
    frame #1: 0x00000001002ede2c Mailable`mailcore::IMAPOperation::setSession(this=0x0000000129b1f720, session=0x0000000125e0cc60) + 172 at MCIMAPOperation.cpp:43
    frame #2: 0x000000010030162c Mailable`mailcore::IMAPAsyncConnection::disconnectOperation(this=0x0000000125e0cc60) + 92 at MCIMAPAsyncConnection.cpp:260
    frame #3: 0x0000000100301970 Mailable`mailcore::IMAPAsyncConnection::tryAutomaticDisconnectAfterDelay(this=0x0000000125e0cc60, context=0x0000000000000000) + 44 at MCIMAPAsyncConnection.cpp:327
    frame #4: 0x00000001002b0e2c Mailable`::___ZN8mailcore6Object38performMethodOnDispatchQueueAfterDelayEMS0_FvPvES1_S1_d_block_invoke((null)=<unavailable>, cancel=false) + 188 at MCObject.cpp:348
    frame #5: 0x00000001002b10dc Mailable`::___ZN8mailcore6Object38performMethodOnDispatchQueueAfterDelayEMS0_FvPvES1_S1_d_block_invoke.8((null)=<unavailable>) + 140 at MCObject.cpp:361
    frame #6: 0x0000000101ac5a7c libdispatch.dylib`_dispatch_call_block_and_release + 24
    frame #7: 0x0000000101ac5a3c libdispatch.dylib`_dispatch_client_callout + 16
    frame #8: 0x0000000101ad1cc8 libdispatch.dylib`_dispatch_after_timer_callback + 148
    frame #9: 0x0000000101ac5a3c libdispatch.dylib`_dispatch_client_callout + 16
    frame #10: 0x0000000101addde0 libdispatch.dylib`_dispatch_source_latch_and_call + 2848
    frame #11: 0x0000000101ac7fe0 libdispatch.dylib`_dispatch_source_invoke + 808
    frame #12: 0x0000000101ad02b0 libdispatch.dylib`_dispatch_async_redirect_invoke + 288
    frame #13: 0x0000000101ac5a3c libdispatch.dylib`_dispatch_client_callout + 16
    frame #14: 0x0000000101ad4c9c libdispatch.dylib`_dispatch_root_queue_drain + 2344
    frame #15: 0x0000000101ad4364 libdispatch.dylib`_dispatch_worker_thread3 + 132
    frame #16: 0x00000001806a5470 libsystem_pthread.dylib`_pthread_wqthread + 1092
    frame #17: 0x00000001806a5020 libsystem_pthread.dylib`start_wqthread + 4
(lldb) 
dinhvh commented 7 years ago

Do you have more context, code sample, etc?

rlaferla commented 7 years ago

Sorry, I've been out of the country for the past week. Let me see what I can find.

shidaying commented 7 years ago

OK, thanks very much 原始邮件 发件人:Robert La Ferlanotifications@github.com 收件人:MailCore/mailcore2mailcore2@noreply.github.com 发送时间:2016年11月28日(周一) 18:31 主题:Re: [MailCore/mailcore2] MCIMAPAsyncConnection EXC_BAD_ACCESS (#1572)

Sorry, I've been out of the country for the past week. Let me see what I can find. — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

rlaferla commented 7 years ago

Using the latest Mailcore branch, this crash has been occurring in afterMain(). I added a check for a nil session and it seems to have gone away. Here's my fix:

void IMAPOperation::afterMain()
{
    if (mSession->session() != nil && mSession->session()->isAutomaticConfigurationDone()) {
        mSession->owner()->automaticConfigurationDone(mSession->session());
        mSession->session()->resetAutomaticConfigurationDone();

    }
}
rlaferla commented 7 years ago

The above code does not fix the issue. I am trying this instead. Is my fix correct to not execute afterMain() if the operation was cancelled? How about the retain before the callback?

void OperationQueue::callbackOnMainThread(Operation * op)
{
    // Move call to afterMain() to after check for cancelled
    if (op->isCancelled())
        return;

    op->afterMain();

    if (op->callback() != NULL) {
        op->callback()->operationFinished(op);
    }
}

then in OperationQueue::runOperations()

        if (!op->isCancelled()) {
            retain(); // Added call to retain to prevent extra release
            performOnCallbackThread(op, (Object::Method) &OperationQueue::callbackOnMainThread, op, true);
        }
Fengzhiwuyu commented 6 years ago

In the void Object::performMethodOnDispatchQueueAfterDelay(Method method, void context, void targetDispatchQueue, double delay),when run dupCancelableBlock(false) will crash on

dispatch_queue_t IMAPAsyncConnection::dispatchQueue() { return mQueue->dispatchQueue(); //EXC_BAD_ACCESS }

it happend more than 5 times crash here.