BoboTiG / python-mss

An ultra fast cross-platform multiple screenshots module in pure Python using ctypes.
https://pypi.org/project/mss/
MIT License
998 stars 88 forks source link

ThreadSafety: gdi32.GetDIBits() failed #198

Closed anawkward closed 1 year ago

anawkward commented 3 years ago

General information:

Description of the warning/error

import threading
import mss
import time

region1 = (0,0,1900,1200)
region2 = (0,0,100,100)

# A) make a grabbing thread

class a_thread(threading.Thread):
    def run(self):
        sct = mss.mss()
        while True:
            sct.grab(region1)
            time.sleep(1)

t = a_thread()
t.start()

time.sleep(1)

# B) grab

sct = mss.mss()
x = sct.grab(monitor=region2)

# the codes above gives an {ScreenShotError("gdi32.GetDIBits() failed.")} Exception.

Full message

Exception in thread Thread-8: Traceback (most recent call last): File "C:\Anaconda3\lib\threading.py", line 917, in _bootstrap_inner self.run() File "", line 12, in run File "C:\Anaconda3\lib\site-packages\mss\base.py", line 88, in grab return self._grab_impl(monitor) File "C:\Anaconda3\lib\site-packages\mss\windows.py", line 285, in _grab_impl raise ScreenShotError("gdi32.GetDIBits() failed.") mss.exception.ScreenShotError: gdi32.GetDIBits() failed.

Other details

I think the error is related with the thread safety of mss.mss(). I did some A/B tests to reproduce it. 1) when region1 = region2, it was okay. error didn't appear. 2) when (B) is done before (A), like (B) -> (A) -> (B), it was okay. no error appeared.

I guess the cause is somewhere around the initialization of mss.mss() and a grab() method does something on the initialization. I hope this issue helps to improve thread safety. contact me for any further information if needed.

BoboTiG commented 2 years ago

@anawkward would you be able to retry with changes from #211?

FlorinPT commented 2 years ago

@anawkward can you help me

CTPaHHuK-HEbA commented 2 years ago

@FlorinPT Check closed issue #212