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

Crash on macOS 10.3.5 with IDLE operation running #1751

Open triton3 opened 6 years ago

triton3 commented 6 years ago

This is an intermittent crash with IDLE operation on macOS we have been observing, when our app is running over several days continuously (a couple of weeks or more). See crash report below:

Thread 23 Crashed:
0   libsystem_kernel.dylib          0x00007fff78f97e3e __pthread_kill + 10
1   libsystem_pthread.dylib         0x00007fff790d6150 pthread_kill + 333
2   libsystem_c.dylib               0x00007fff78ef43b1 __abort + 144
3   libsystem_c.dylib               0x00007fff78ef4321 abort + 142
4   com.libmailcore.MailCore        0x0000000109329a11 MCAssertInternal + 81
5   com.libmailcore.MailCore        0x0000000109348b60 mailcore::IMAPSession::setup() + 64
6   com.libmailcore.MailCore        0x0000000109348e53 mailcore::IMAPSession::connect(mailcore::ErrorCode*) + 35
7   com.libmailcore.MailCore        0x0000000109349cc8 mailcore::IMAPSession::connectIfNeeded(mailcore::ErrorCode*) + 104
8   com.libmailcore.MailCore        0x0000000109349d16 mailcore::IMAPSession::loginIfNeeded(mailcore::ErrorCode*) + 54
9   com.libmailcore.MailCore        0x000000010934b8b2 mailcore::IMAPSession::selectIfNeeded(mailcore::String*, mailcore::ErrorCode*) + 66
10  com.libmailcore.MailCore        0x000000010937b022 mailcore::IMAPIdleOperation::main() + 130
11  com.libmailcore.MailCore        0x000000010933ba81 mailcore::OperationQueue::runOperations() + 769
12  com.libmailcore.MailCore        0x000000010933b775 mailcore::OperationQueue::runOperationsOnThread(mailcore::OperationQueue*) + 21
13  libsystem_pthread.dylib         0x00007fff790d36c1 _pthread_body + 340
14  libsystem_pthread.dylib         0x00007fff790d356d _pthread_start + 377
15  libsystem_pthread.dylib         0x00007fff790d2c5d thread_start + 13

Thread 23 crashed with X86 Thread State (64-bit):
 rax: 0x0000000000000000  rbx: 0x000070022d5cc000  rcx: 0x000070022d5cb9c8  rdx: 0x0000000000000000
 rdi: 0x0000000000467c03  rsi: 0x0000000000000006  rbp: 0x000070022d5cba00  rsp: 0x000070022d5cb9c8
  r8: 0x0000000000000000   r9: 0x0000000000989680  r10: 0x0000000000000000  r11: 0x0000000000000206
 r12: 0x0000000000467c03  r13: 0x0000000000000000  r14: 0x0000000000000006  r15: 0x000000000000002d
 rip: 0x00007fff78f97e3e  rfl: 0x0000000000000206  cr2: 0x0000001b064cf000

Logical CPU:     0
Error Code:      0x02000148
Trap Number:     133

It looks like mImap property in IMAPSession is not NULL but the assert condition expects it to be null, and the assert is causing the crash.

void IMAPSession::setup()
{
    MCAssert(mImap == NULL); // <----- Crashes here

    mImap = mailimap_new(0, NULL);
    mailimap_set_timeout(mImap, timeout());
    mailimap_set_progress_callback(mImap, body_progress, IMAPSession::items_progress, this);
    mailimap_set_logger(mImap, logger, this);
}

We are attempting to debug this, but given that this is sporadic, it is not easy to reproduce.

Question: What is the scenario in which mImap property should be NULL? Any help/hints to resolve this would be greatly appreciated.

triton3 commented 6 years ago

Does mailcore disconnect the IMAPSession when IDLE operation is terminated?

triton3 commented 6 years ago

I am still facing this issue intermittently. Please see code below. It crashes when idle operation is started. As you can see, I am creating a new session for the Idle operation.

    // always create a new session for IDLE
    let newSession = MCOIMAPSession().with(carrierSettings: self.carrier)
    self.session = newSession
    let hostname = self.session?.hostname ?? ""
    self.idleOperation = newSession.idleOperation(withFolder: self.folderPath, lastKnownUID: self.lastCheckedUID.uint32Value)

    Log.Debug("ImapIdleConnection::\(#line): ============================================================================")
    Log.Debug("ImapIdleConnection::\(#line): Starting IDLE connection to \(self.folderPath) folder on \(hostname) with last known UID \(self.lastCheckedUID)...")
    Log.Debug("ImapIdleConnection::\(#line): ============================================================================")

    // start idle op
    self.idleOperation?.start {[weak self] (error: Error?) in
                ....
    }

Here is the log output:

2018-08-03 13:02:26.100159-0400 App[28207:1129567] ImapIdleConnection::122: ============================================================================
2018-08-03 13:02:26.100137-0400 App[28207:1129567] ImapIdleConnection::123: Starting IDLE connection to <private> folder on <private> with last known UID 0...
2018-08-03 13:02:26.100139-0400 App[28207:1160900] ImapIdleConnection::124: ============================================================================
~/mailcore2-master/src/core/imap/MCIMAPSession.cpp:612: assert mImap == NULL
dinhvh commented 6 years ago

I think the IMAPSession disconnect after 30 sec when operations are terminated. That said, it shouldn't lead to this crash. It should reconnect automatically. Are you trying to use MCOIMAPSession from several threads?

dinhvh commented 6 years ago

Could you show a full minimal app example so that I can repro?

triton3 commented 6 years ago

@dinhviethoa Thank you for your response.

Could you show a full minimal app example so that I can repro?

The problem is that it is not easily/reliably reproducible (happens once in several weeks when the app has been left running).

I think the IMAPSession disconnect after 30 sec when operations are terminated. That said, it shouldn't lead to this crash. It should reconnect automatically. Are you trying to use MCOIMAPSession from several threads?

Hmm. I always disconnect an existing connection before creating a new one for idle. But I now wonder about the threading issue with the session. Once I create the session for Idle it is not used by any other operation, but thanks for the hint. I will investigate if that is happening as a corner case.