classification
Title: Thread safety issue with MagickMock __str__: sometimes returns MagickMock instead of str
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.6, Python 3.5, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Stanisław Skonieczny (Uosiu), Yoichi Nakayama, iritkatriel, michael.foord, pitrou
Priority: normal Keywords:

Created on 2016-03-21 08:13 by Stanisław Skonieczny (Uosiu), last changed 2021-02-22 10:51 by iritkatriel.

Messages (6)
msg262104 - (view) Author: Stanisław Skonieczny (Uosiu) (Stanisław Skonieczny (Uosiu)) Date: 2016-03-21 08:13
This bug results in raising TypeError: __str__ returned non-string (type MagicMock)
Following program can reproduce it:

```
from threading import Thread
from mock.mock import MagicMock


def main():
    mocks = [MagicMock() for _ in range(1000)]

    def in_thread():
        for m in mocks:
            str(m)

    threads = [Thread(target=in_thread) for _ in range(10)]
    for thread in threads:
        thread.start()
    for thread in threads:
        thread.join()


if __name__ == '__main__':
    main()
```

For me it rasies few times:

```
Exception in thread Thread-6:
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/threading.py", line 923, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.5/threading.py", line 871, in run
    self._target(*self._args, **self._kwargs)
  File "../misc/magic_mock_str_bug.py", line 11, in in_thread
    str(m)
TypeError: __str__ returned non-string (type MagicMock)
```
msg272735 - (view) Author: Yoichi Nakayama (Yoichi Nakayama) Date: 2016-08-15 08:47
It is not a bug of MagicMock. It is a problem of the sample program.
Calling str to mock object cause not only read access,
it also write to related objects. So there is a race condition.
msg387178 - (view) Author: Irit Katriel (iritkatriel) * (Python triager) Date: 2021-02-17 18:26
The documentation has examples how to set up a mock's __str__.

https://docs.python.org/3/library/unittest.mock.html
msg387507 - (view) Author: Stanisław Skonieczny (Uosiu) (Stanisław Skonieczny (Uosiu)) Date: 2021-02-22 09:17
However there is still nothing in the docs that you have to mock `__str__`
by yourself
when using mock object with multiple threads. Otherwise calling `__str__`
may result
with raising exception if you are unlucky.

Stanisław Skonieczny

On Wed, Feb 17, 2021 at 7:26 PM Irit Katriel <report@bugs.python.org> wrote:

>
> Irit Katriel <iritkatriel@yahoo.com> added the comment:
>
> The documentation has examples how to set up a mock's __str__.
>
> https://docs.python.org/3/library/unittest.mock.html
>
> ----------
> nosy: +iritkatriel
> resolution:  -> not a bug
> stage:  -> resolved
> status: open -> closed
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue26600>
> _______________________________________
>
msg387509 - (view) Author: Irit Katriel (iritkatriel) * (Python triager) Date: 2021-02-22 09:55
Why is this only relevant to multiple thread?
msg387511 - (view) Author: Stanisław Skonieczny (Uosiu) (Stanisław Skonieczny (Uosiu)) Date: 2021-02-22 10:10
When you just create a magick mock and then call `__str__` on it, it never
throws an exception and always return a string.
But... when you create a magick mock and then call `__str__` from two
threads concurrently, one of them will raise an exception.

Race is as follows:
1. Thread 1 creates magick mock m.
2. Thread 1 enters `m.__str__` it starts some internal preparations. It
does not exit `__str__` yet.
3. Thread 2 enters `m.__str__`.
In effect one of this threads will try to return `MagickMock` instance
instead of `str` object, which if forbidden by python.
Some low-level python check will raise following exception: `TypeError:
__str__ returned non-string (type MagicMock)`.

Stanisław Skonieczny

On Mon, Feb 22, 2021 at 10:56 AM Irit Katriel <report@bugs.python.org>
wrote:

>
> Irit Katriel <iritkatriel@yahoo.com> added the comment:
>
> Why is this only relevant to multiple thread?
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <https://bugs.python.org/issue26600>
> _______________________________________
>
History
Date User Action Args
2021-02-22 10:51:03iritkatrielsetresolution: not a bug ->
title: MagickMock __str__ sometimes returns MagickMock instead of str -> Thread safety issue with MagickMock __str__: sometimes returns MagickMock instead of str
2021-02-22 10:10:50Stanisław Skonieczny (Uosiu)setmessages: + msg387511
2021-02-22 09:55:55iritkatrielsetmessages: + msg387509
2021-02-22 09:53:44iritkatrielsetstatus: closed -> open
2021-02-22 09:17:07Stanisław Skonieczny (Uosiu)setmessages: + msg387507
2021-02-17 18:26:12iritkatrielsetstatus: open -> closed

nosy: + iritkatriel
messages: + msg387178

resolution: not a bug
stage: resolved
2016-08-15 08:47:02Yoichi Nakayamasetnosy: + Yoichi Nakayama
messages: + msg272735
2016-03-21 10:45:23SilentGhostsetnosy: + pitrou, michael.foord

versions: + Python 3.6, - Python 3.2, Python 3.3, Python 3.4
2016-03-21 08:13:06Stanisław Skonieczny (Uosiu)create