Add new .idle() method to listen for updates from MainThread

This commit is contained in:
Lonami Exo 2017-10-22 13:15:52 +02:00
parent 8057cea294
commit b04eed82eb

View File

@ -5,6 +5,7 @@ import warnings
from datetime import timedelta, datetime from datetime import timedelta, datetime
from hashlib import md5 from hashlib import md5
from io import BytesIO from io import BytesIO
from signal import signal, SIGINT, SIGTERM, SIGABRT
from threading import Lock from threading import Lock
from time import sleep from time import sleep
@ -785,14 +786,31 @@ class TelegramBareClient:
) )
self._recv_thread.start() self._recv_thread.start()
# By using this approach, another thread will be def _signal_handler(self, signum, frame):
# created and started upon connection to constantly read if self._user_connected:
# from the other end. Otherwise, manual calls to .receive() self.disconnect()
# must be performed. The MtProtoSender cannot be connected, else:
# or an error will be thrown. self._logger.debug('Forcing exit...')
# os._exit(1)
# This way, sending and receiving will be completely independent.
def _recv_thread_impl(self): def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
"""
Idles the program by looping forever and listening for updates
until one of the signals are received, which breaks the loop.
:param stop_signals:
Iterable containing signals from the signal module that will
be subscribed to TelegramClient.disconnect() (effectively
stopping the idle loop), which will be called on receiving one
of those signals.
:return:
"""
if self._spawn_read_thread and not self._on_read_thread():
raise ValueError('Can only idle if spawn_read_thread=False')
for sig in stop_signals:
signal(sig, self._signal_handler)
while self._user_connected: while self._user_connected:
try: try:
if datetime.now() > self._last_ping + self._ping_delay: if datetime.now() > self._last_ping + self._ping_delay:
@ -810,10 +828,24 @@ class TelegramBareClient:
while self._user_connected and not self._reconnect(): while self._user_connected and not self._reconnect():
sleep(0.1) # Retry forever, this is instant messaging sleep(0.1) # Retry forever, this is instant messaging
# By using this approach, another thread will be
# created and started upon connection to constantly read
# from the other end. Otherwise, manual calls to .receive()
# must be performed. The MtProtoSender cannot be connected,
# or an error will be thrown.
#
# This way, sending and receiving will be completely independent.
def _recv_thread_impl(self):
# This thread is "idle" (only listening for updates), but also
# excepts everything unlike the manual idle because it should
# not crash.
while self._user_connected:
try:
self.idle(stop_signals=tuple())
except Exception as error: except Exception as error:
# Unknown exception, pass it to the main thread # Unknown exception, pass it to the main thread
self._logger.debug( self._logger.error(
'[ERROR] Unknown error on the read thread, please report', 'Unknown error on the read thread, please report',
error error
) )
@ -835,7 +867,6 @@ class TelegramBareClient:
# infinite loop where all we do is raise an exception, so # infinite loop where all we do is raise an exception, so
# add a little sleep to avoid the CPU usage going mad. # add a little sleep to avoid the CPU usage going mad.
sleep(0.1) sleep(0.1)
break
self._recv_thread = None self._recv_thread = None