Skip to content

Not thread-safe without calling tqdm.get_lock() first #982

@duckythescientist

Description

@duckythescientist

Calling tqdm.write(...) in two racing threads will throw an exception unless tqdm.get_lock() is called first. I'm not sure if calling tqdm.get_lock() addresses the root cause, but at least it seems to have fixed it for me.

Example:

#!/usr/bin/env python3

import threading

from tqdm import tqdm


def race_write():
    # while True:
    for j in range(100):
        tqdm.write("spam")

def race_write2():
    # while True:
    for j in range(100):
        tqdm.write("eggs!")


# tqdm.get_lock()
t_write = threading.Thread(target=race_write)
t_write2 = threading.Thread(target=race_write2)
t_write.start()
t_write2.start()

After a few writes, the following gets thrown:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 926, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "tqdm_fail.py", line 11, in race_write
    tqdm.write("spam")
  File "/home/duck/.local/lib/python3.7/site-packages/tqdm/std.py", line 586, in write
    fp.write(end)
  File "/usr/lib/python3.7/contextlib.py", line 119, in __exit__
    next(self.gen)
  File "/home/duck/.local/lib/python3.7/site-packages/tqdm/std.py", line 616, in external_write_mode
    cls._lock.release()
  File "/home/duck/.local/lib/python3.7/site-packages/tqdm/std.py", line 93, in release
    lock.release()
AssertionError: attempt to release recursive lock not owned by thread

Version info:

Python 3.7.5 (default, Apr 19 2020, 20:18:17) 
[GCC 9.2.1 20191008] on linux
>>> import tqdm, sys
>>> print(tqdm.__version__, sys.version, sys.platform)
4.46.0 3.7.5 (default, Apr 19 2020, 20:18:17) 
[GCC 9.2.1 20191008] linux

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions