From 0f4bd6347ff7ea0f69c300ff8aea3efba23b2874 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Fri, 24 Apr 2020 01:56:07 +0200 Subject: [PATCH] stop threads and call close() on switching account the imap-/mvbox-/sentbox-/smtp-threads needs to be terminated before dc_close() can be called successfully. if this is not done, they are hanging around, and, even worse, if an account is opened _again_, there are now two threads working on the database which lead to duplicated messages. note, that this issue is only related to duplicated messages if ever an account was selected, which, however, might be the same as the current. --- jni/dc_wrapper.c | 6 ++++ src/com/b44t/messenger/DcContext.java | 1 + .../securesms/connect/AccountManager.java | 2 ++ .../connect/ApplicationDcContext.java | 35 ++++++++++++++++--- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index b023e08a2..ef74c388b 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -387,6 +387,12 @@ JNIEXPORT void Java_com_b44t_messenger_DcContext_performSmtpIdle(JNIEnv *env, jo } +JNIEXPORT void Java_com_b44t_messenger_DcContext_interruptSmtpIdle(JNIEnv *env, jobject obj) +{ + dc_interrupt_smtp_idle(get_dc_context(env, obj)); +} + + JNIEXPORT void Java_com_b44t_messenger_DcContext_maybeNetwork(JNIEnv *env, jobject obj) { dc_maybe_network(get_dc_context(env, obj)); diff --git a/src/com/b44t/messenger/DcContext.java b/src/com/b44t/messenger/DcContext.java index 3bb29b025..4848b9ae5 100644 --- a/src/com/b44t/messenger/DcContext.java +++ b/src/com/b44t/messenger/DcContext.java @@ -106,6 +106,7 @@ public class DcContext { public native void performSmtpJobs (); public native void performSmtpIdle (); + public native void interruptSmtpIdle (); public native void maybeNetwork (); public native void setConfig (String key, String value); diff --git a/src/org/thoughtcrime/securesms/connect/AccountManager.java b/src/org/thoughtcrime/securesms/connect/AccountManager.java index 32aa176ee..203646f02 100644 --- a/src/org/thoughtcrime/securesms/connect/AccountManager.java +++ b/src/org/thoughtcrime/securesms/connect/AccountManager.java @@ -93,6 +93,8 @@ public class AccountManager { // create an empty DcContext object - this will be set up then, starting with // getSelectedAccount() ApplicationContext appContext = (ApplicationContext)context.getApplicationContext(); + appContext.dcContext.stopThreads(); + appContext.dcContext.close(); appContext.dcContext = new ApplicationDcContext(context); } diff --git a/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java b/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java index 7c69fa9fe..86cb71bb6 100644 --- a/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java +++ b/src/org/thoughtcrime/securesms/connect/ApplicationDcContext.java @@ -296,6 +296,8 @@ public class ApplicationDcContext extends DcContext { public final static int INTERRUPT_IDLE = 0x01; // interrupt idle if the thread is already running + public boolean run = true; + public void startThreads(int flags) { synchronized (threadsCritical) { @@ -303,7 +305,7 @@ public class ApplicationDcContext extends DcContext { imapThread = new Thread(() -> { Log.i(TAG, "###################### IMAP-Thread started. ######################"); - while (true) { + while (run) { imapWakeLock.acquire(); performImapJobs(); performImapFetch(); @@ -313,6 +315,7 @@ public class ApplicationDcContext extends DcContext { } performImapIdle(); } + Log.i(TAG, "!!!!!!!!!!!! IMAP-Thread stopped"); }, "imapThread"); imapThread.setPriority(Thread.NORM_PRIORITY); imapThread.start(); @@ -327,7 +330,7 @@ public class ApplicationDcContext extends DcContext { mvboxThread = new Thread(() -> { Log.i(TAG, "###################### MVBOX-Thread started. ######################"); - while (true) { + while (run) { mvboxWakeLock.acquire(); performMvboxJobs(); performMvboxFetch(); @@ -337,6 +340,7 @@ public class ApplicationDcContext extends DcContext { } performMvboxIdle(); } + Log.i(TAG, "!!!!!!!!!!!! MVBOX-Thread stopped"); }, "mvboxThread"); mvboxThread.setPriority(Thread.NORM_PRIORITY); mvboxThread.start(); @@ -351,13 +355,14 @@ public class ApplicationDcContext extends DcContext { sentboxThread = new Thread(() -> { Log.i(TAG, "###################### SENTBOX-Thread started. ######################"); - while (true) { + while (run) { sentboxWakeLock.acquire(); performSentboxJobs(); performSentboxFetch(); sentboxWakeLock.release(); performSentboxIdle(); } + Log.i(TAG, "!!!!!!!!!!!! SENTBOX-Thread stopped"); }, "sentboxThread"); sentboxThread.setPriority(Thread.NORM_PRIORITY-1); sentboxThread.start(); @@ -370,7 +375,7 @@ public class ApplicationDcContext extends DcContext { if (smtpThread == null || !smtpThread.isAlive()) { smtpThread = new Thread(() -> { Log.i(TAG, "###################### SMTP-Thread started. ######################"); - while (true) { + while (run) { smtpWakeLock.acquire(); performSmtpJobs(); smtpWakeLock.release(); @@ -379,6 +384,7 @@ public class ApplicationDcContext extends DcContext { } performSmtpIdle(); } + Log.i(TAG, "!!!!!!!!!!!! SMTP-Thread stopped"); }, "smtpThread"); smtpThread.setPriority(Thread.MAX_PRIORITY); smtpThread.start(); @@ -397,6 +403,27 @@ public class ApplicationDcContext extends DcContext { } } + public void stopThreads() { + Log.i(TAG, "!!!!!!!!!!!! Stopping threads ..."); + run = false; + synchronized (threadsCritical) { + if (imapThread!=null) { interruptImapIdle(); } + if (mvboxThread!=null) { interruptMvboxIdle(); } + if (sentboxThread!=null) { interruptSentboxIdle(); } + if (smtpThread!=null) { interruptSmtpIdle(); } + while (true) { + if ( (imapThread==null || !imapThread.isAlive()) + && (mvboxThread==null || !mvboxThread.isAlive()) + && (sentboxThread==null || !sentboxThread.isAlive()) + && (smtpThread==null || !smtpThread.isAlive())) { + break; + } + Util.sleep(100); + } + } + Log.i(TAG, "!!!!!!!!!!!! threads stopped"); + } + /*********************************************************************************************** * Tools