diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py index 9cb620c15..44b9cac22 100644 --- a/python/src/deltachat/account.py +++ b/python/src/deltachat/account.py @@ -15,7 +15,7 @@ from .cutil import as_dc_charpointer, from_dc_charpointer, iter_array, DCLot from .chat import Chat from .message import Message, map_system_message from .contact import Contact -from .tracker import ImexTracker +from .tracker import ImexTracker, ConfigureTracker from . import hookspec, iothreads from .eventlogger import FFIEvent, FFIEventLogger @@ -169,7 +169,7 @@ class Account(object): :returns: True if account is configured. """ - return bool(lib.dc_is_configured(self._dc_context)) + return True if lib.dc_is_configured(self._dc_context) else False def set_avatar(self, img_path): """Set self avatar. @@ -576,7 +576,9 @@ class Account(object): if not self.is_configured(): if not self.get_config("addr") or not self.get_config("mail_pw"): raise MissingCredentials("addr or mail_pwd not set in config") - lib.dc_configure(self._dc_context) + with self.temp_plugin(ConfigureTracker()) as config_tracker: + lib.dc_configure(self._dc_context) + config_tracker.wait_finish() lib.dc_context_run(self._dc_context) def is_started(self): @@ -586,6 +588,11 @@ class Account(object): """ wait until shutdown of this account has completed. """ self._shutdown_event.wait() + def stop_scheduler(self): + """ stop core scheduler if it is running. """ + self.ac_log_line("context_shutdown (stop core scheduler)") + lib.dc_context_shutdown(self._dc_context) + def shutdown(self, wait=True): """ shutdown account, stop threads and close and remove underlying dc_context.""" @@ -593,13 +600,13 @@ class Account(object): if dc_context is None: return + self.stop_ongoing() if self._threads.is_started(): - self.stop_ongoing() self.ac_log_line("stop threads") self._threads.stop(wait=False) - self.ac_log_line("context shutdown") - lib.dc_context_shutdown(dc_context) + self.stop_scheduler() + self.ac_log_line("dc_close") lib.dc_close(dc_context) self.ac_log_line("wait threads for real") diff --git a/python/src/deltachat/iothreads.py b/python/src/deltachat/iothreads.py index ce9fd8b16..62792b133 100644 --- a/python/src/deltachat/iothreads.py +++ b/python/src/deltachat/iothreads.py @@ -51,6 +51,14 @@ class IOThreads: except StopIteration: break self.account.ac_log_line("calling hook name={} kwargs={}".format(ev.name, ev.kwargs)) - ev.call_hook() + try: + ev.call_hook() + except Exception: + # don't bother logging this error + # because dc_close() was concurrently called + # and core API starts failing after that. + if not self._thread_quitflag: + raise + diff --git a/python/tests/test_account.py b/python/tests/test_account.py index 6034534af..3387163bb 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -473,8 +473,17 @@ class TestOfflineChat: num_contacts = len(chat.get_contacts()) assert num_contacts == 11 - # perform plugin hooks - ac1._handle_current_events() + # let's make sure the events perform plugin hooks + def wait_events(cond): + now = time.time() + while time.time() < now + 5: + if cond(): + break + time.sleep(0.1) + else: + pytest.fail("failed to get events") + + wait_events(lambda: len(in_list) == 10) assert len(in_list) == 10 chat_contacts = chat.get_contacts() @@ -493,7 +502,7 @@ class TestOfflineChat: chat.remove_contact(contacts[3]) assert len(chat.get_contacts()) == 9 - ac1._handle_current_events() + wait_events(lambda: len(in_list) == 2) assert len(in_list) == 2 assert in_list[0][0] == "removed" assert in_list[0][1] == chat diff --git a/python/x.py b/python/x.py new file mode 100644 index 000000000..6ad780bc3 --- /dev/null +++ b/python/x.py @@ -0,0 +1,32 @@ + +import deltachat +import os +import shutil +from deltachat.capi import lib + +try: + os.remove("/tmp/db") +except: + pass +try: + shutil.rmtree("/tmp/db-blobs") +except: + pass + + +acc = deltachat.Account("/tmp/db", logging=True) +acc.set_config("addr", "tmp.hjfcq@five.chat") +acc.set_config("mail_pw", "aihWNtLuRJgV") +acc.start() # lib.dc_configure + lib.dc_context_run +assert acc.is_configured() +acc.stop_scheduler() + +while 1: + print("starting scheduler") + acc.start() + print("stopping scheduler") + acc.stop_scheduler() + +contact = acc.create_contact("holger@deltachat.de") +chat = acc.create_chat_by_contact(contact) +chat.send_text("hello")