Skip to content

Commit

Permalink
Use the idling state instead checking if read thread is present
Browse files Browse the repository at this point in the history
This caused some multithreading bugs, for instance, when there was
no read thread and the main thread was idling, and there were some
update workers. Several threads would try to read from the socket
at the same time (since there's no lock for reading), causing
reads to be corrupted and receiving "invalid packet lengths"
from the network. Closes #538.
  • Loading branch information
Lonami committed Jan 14, 2018
1 parent 87a77e7 commit 8be7e76
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion telethon/telegram_bare_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ def __init__(self, session, api_id, api_hash,
# if the user has left enabled such option.
self._spawn_read_thread = spawn_read_thread
self._recv_thread = None
self._idling = threading.Event()

# Default PingRequest delay
self._last_ping = datetime.now()
Expand Down Expand Up @@ -438,8 +439,9 @@ def __call__(self, *requests, retries=5):

# Determine the sender to be used (main or a new connection)
__log__.debug('Invoking %s', which)
call_receive = \
not self._idling.is_set() or self._reconnect_lock.locked()

call_receive = self._recv_thread is None or self._reconnect_lock.locked()
for retry in range(retries):
result = self._invoke(call_receive, *requests)
if result is not None:
Expand Down Expand Up @@ -829,6 +831,7 @@ def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
if self._spawn_read_thread and not self._on_read_thread():
raise RuntimeError('Can only idle if spawn_read_thread=False')

self._idling.set()
for sig in stop_signals:
signal(sig, self._signal_handler)

Expand Down Expand Up @@ -857,7 +860,11 @@ def idle(self, stop_signals=(SIGINT, SIGTERM, SIGABRT)):
with self._reconnect_lock:
while self._user_connected and not self._reconnect():
sleep(0.1) # Retry forever, this is instant messaging
except:
self._idling.clear()
raise

self._idling.clear()
__log__.info('Connection closed by the user, not reading anymore')

# By using this approach, another thread will be
Expand Down

0 comments on commit 8be7e76

Please sign in to comment.