python-mss icon indicating copy to clipboard operation
python-mss copied to clipboard

Xvfb error while trying to open multiple xvfb screens in single python session

Open mudassirkhan19 opened this issue 2 years ago • 7 comments

General information:

  • OS name: Ubuntu
  • OS version: 20.04
  • OS architecture: 64 bits
  • Resolutions:
    • Monitor 1: 1920x1080
  • Python version: 3.8.10
  • MSS version: 6.1.0

For GNU/Linux users:

  • Display server protocol and version, if known: Xorg
  • Desktop Environment: Gnome
  • Composite Window Manager name and version: Not sure

Description of the warning/error

The error comes when I try to call mss.mss() in a single python session with two different Xvfb screens.

Full message

XIO: fatal IO error 0 (Success) on X server ":3" after 8 requests (8 known processed) with 0 events remaining.

Other details

Steps to reproduce:

from xvfbwrapper import Xvfb
import mss
import os

xvfb = Xvfb(width=1920, height=1080, colordepth=24)
xvfb.start()

with mss.mss() as sct:
    pass
xvfb.stop()

xvfb = Xvfb(width=1920, height=1080, colordepth=24)
xvfb.start()

with mss.mss() as sct:
    pass

The error pops up exactly on this line

mudassirkhan19 avatar Jan 19 '22 14:01 mudassirkhan19

Could you try to reset that attribute before the second use of MSS?

from mss.linux import MSS

# (...)
xvfb.stop()

MSS._display_dict.clear()

xvfb = Xvfb(width=1920, height=1080, colordepth=24)
# (...)

BoboTiG avatar Jan 19 '22 22:01 BoboTiG

thanks @BoboTiG ! I have been trying to resolve this bug since two days.

mudassirkhan19 avatar Jan 20 '22 05:01 mudassirkhan19

Great! I could introduce a mss.reset_internal_state() to hide implementation details. Or maybe shorter: mss.reset(). With a good documentation it should help with such situation.

BoboTiG avatar Jan 20 '22 07:01 BoboTiG

Shouldn't the context manager take care of this? this can just happen behind the scenes, just a thought.

mudassirkhan19 avatar Jan 20 '22 07:01 mudassirkhan19

Actually those internal details were added for performance and memory leak reasons. Your situation is not so frequent, so I would go with the new function to clear the internal state.

BoboTiG avatar Jan 20 '22 08:01 BoboTiG

Encountered another issue with this, this time its a too many open files error, the open connection originates here: self.xlib.XOpenDisplay(disp) So basically we aren't closing our connection to the X11 server, a little digging led me to an XCloseDisplay function from here. So wrote a wrapper for my usecase:

from contextlib import contextmanager
import sys

@contextmanager
def mss_wrapper():
    try:
        with mss.mss() as sct:
            yield sct
    finally:
        if sys.platform == "linux":
            from mss.linux import MSS
            import ctypes

            x11 = ctypes.util.find_library("X11")  # type: ignore
            xlib = ctypes.cdll.LoadLibrary(x11)
            for _, display in MSS._display_dict.items():
                xlib.XCloseDisplay(display)
            MSS._display_dict.clear()

mudassirkhan19 avatar Feb 14 '22 12:02 mudassirkhan19

I've run into the same issue as @mudassirkhan19 (thanks for the wrapper by the way!).

I feel like it makes a lot of sense for the display to get closed and the dict cleared on the context exit, in which case would someone avoid this?

Also, out of curiosity, why share the display among all MSS instances in a thread instead of each MSS instance having it's own? Right now one can only use MSS to connect to one display per thread, clearing the dict solves this partially but you can't have two MSS instances connected to different displays in the same thread. X apparently doesn't mind multiple connections to the same display per thread since I'm using other libraries each with their own display.

dp-alvarez avatar May 06 '22 23:05 dp-alvarez

@dp-alvarez

Also, out of curiosity, why share the display among all MSS instances in a thread instead of each MSS instance having it's own?

At first, it was to workaround resource leaks. But I now see that it's not a good way, and there may be no way to handle all cases. So I refactored the whole part in #234, and it should be better for most of us.

BoboTiG avatar Apr 08 '23 07:04 BoboTiG