From 9518ea78d139d9ef1c4fbc694a5ef6c122504c46 Mon Sep 17 00:00:00 2001 From: Edouard Tisserant Date: Thu, 20 Apr 2017 16:39:52 +0200 Subject: [PATCH] ENGINE-187 reworked timeout impl and added remaining time return when timeout interrupted by message --- src/sync_mixin.cc | 70 +++++++++++++++++++++++++++++++++++------------ src/sync_mixin.hh | 17 +++++++++--- test/multipEp.py | 1 + 3 files changed, 66 insertions(+), 22 deletions(-) diff --git a/src/sync_mixin.cc b/src/sync_mixin.cc index b0315b1..0aa7d5b 100644 --- a/src/sync_mixin.cc +++ b/src/sync_mixin.cc @@ -70,21 +70,30 @@ namespace pEp { jmp_buf SyncMixIn::env; void *SyncMixIn::_msg; - bool SyncMixIn::running_timeout = false; - bool SyncMixIn::expiring_timeout = false; + + timeout_state_t SyncMixIn::timeout_state = timeout_stopped; + bool SyncMixIn::last_turn = false; + time_t SyncMixIn::remaining_time = 0; int SyncMixIn::inject_sync_msg(void *msg, void *management) { + assert(timeout_state != timeout_canceling); + if(timeout_state == timeout_canceling) return 0; + + assert(timeout_state != timeout_expiring); + if(timeout_state == timeout_expiring) return 0; + _msg = msg; int val = setjmp(env); if (!val){ - if(running_timeout){ + if(timeout_state == timeout_running){ // call python timeout timer cancel auto that = dynamic_cast< SyncMixIn_callback * >( static_cast< SyncMixIn * > (management)); - that->cancelTimeout(); - running_timeout = false; + remaining_time = that->cancelTimeout(); + timeout_state = timeout_canceling; } + last_turn = false; do_sync_protocol(session, management); } return 0; @@ -92,21 +101,39 @@ namespace pEp { void *SyncMixIn::retrieve_next_sync_msg(void *management, time_t *timeout) { - static int twice = 1; - twice = !twice; - - if (!twice){ - if (expiring_timeout){ + if (!last_turn){ + + assert(timeout_state != timeout_running); + if(timeout_state == timeout_running) return NULL; + + switch(timeout_state){ + case timeout_canceling : + *timeout = remaining_time; + break; + case timeout_expiring : + // "1" is arbitrary value !=0, since we don't + // have original timeout value anymore *timeout = 1; - expiring_timeout = true; - } else if (_msg != NULL && *timeout != 0){ + break; + } + + timeout_state = timeout_stopped; + + last_turn = true; + return (void *) _msg; + + } else { + + assert(timeout_state == timeout_stopped); + if(timeout_state != timeout_stopped) return NULL; + + if (*timeout != 0) { // call python timeout timer start auto that = dynamic_cast< SyncMixIn_callback * >( static_cast< SyncMixIn * > (management)); that->setTimeout(*timeout); - running_timeout = true; + timeout_state = timeout_running; } - return (void *) _msg; } longjmp(env, 1); return (void *) 23; @@ -114,12 +141,19 @@ namespace pEp { // to be called from python timeout timer - may GIL protect us void SyncMixIn::onTimeout(){ + assert(timeout_state != timeout_canceling); + if(timeout_state == timeout_canceling) return; + + assert(timeout_state != timeout_expiring); + if(timeout_state == timeout_expiring) return; + _msg = NULL; int val = setjmp(env); if (!val){ - expiring_timeout = true; + timeout_state = timeout_expiring; + + last_turn = false; do_sync_protocol(session, (void*)this); - running_timeout = false; } } @@ -139,9 +173,9 @@ namespace pEp { call_method< void >(_self, "setTimeout", timeout); } - void SyncMixIn_callback::cancelTimeout() + time_t SyncMixIn_callback::cancelTimeout() { - call_method< void >(_self, "cancelTimeout"); + return call_method< time_t >(_self, "cancelTimeout"); } } } diff --git a/src/sync_mixin.hh b/src/sync_mixin.hh index 6a62e96..6104af7 100644 --- a/src/sync_mixin.hh +++ b/src/sync_mixin.hh @@ -6,6 +6,14 @@ namespace pEp { namespace PythonAdapter { + + typedef enum _timeout_state_t { + timeout_stopped, + timeout_running, + timeout_canceling, + timeout_expiring + } timeout_state_t; + class SyncMixIn { public: SyncMixIn() { } @@ -34,7 +42,7 @@ namespace pEp { throw runtime_error("override this method"); } - virtual void cancelTimeout(){ + virtual time_t cancelTimeout(){ throw runtime_error("override this method"); } @@ -46,9 +54,10 @@ namespace pEp { pEp_identity *me, pEp_identity *partner, sync_handshake_signal signal); static jmp_buf env; - static bool running_timeout; - static bool expiring_timeout; static void *_msg; + static timeout_state_t timeout_state; + static bool last_turn; + static time_t remaining_time; static int inject_sync_msg(void *msg, void *management); static void *retrieve_next_sync_msg(void *management, time_t *timeout); }; @@ -67,7 +76,7 @@ namespace pEp { sync_handshake_signal signal); void setTimeout(time_t timeout); - void cancelTimeout(); + time_t cancelTimeout(); }; } } diff --git a/test/multipEp.py b/test/multipEp.py index 44d99ef..4356f46 100644 --- a/test/multipEp.py +++ b/test/multipEp.py @@ -303,6 +303,7 @@ def pEp_instance_run(iname, _own_addresses, conn, _msgs_folders, _handshakes_see def cancelTimeout(self): printi("CANCEL TIMEOUT") + return 42 if not disable_sync: sync_handler = Handler()