txoof / epdlib

Python library for creating and writing modular layouts for e-paper screens
GNU General Public License v3.0
16 stars 8 forks source link

SPI File Handles remain open after refreshes causing eventual OSError [Error 24] and crash #13

Closed txoof closed 3 years ago

txoof commented 3 years ago
03:37:41 epd2in7:getbuffer:378:DEBUG - Horizontal
Traceback (most recent call last):
  File "paperpi.py", line 658, in <module>
  File "paperpi.py", line 641, in main
  File "paperpi.py", line 545, in update_loop
  File "/home/pi/.local/share/virtualenvs/epd_display-ApAYs8Kw/lib/python3.7/site-packages/epdlib/Screen.py", line 361, in writeEPD
  File "/home/pi/.local/share/virtualenvs/epd_display-ApAYs8Kw/lib/python3.7/site-packages/epdlib/Screen.py", line 401, in _full_writeEPD_non_hd
  File "/home/pi/.local/share/virtualenvs/epd_display-ApAYs8Kw/lib/python3.7/site-packages/epdlib/Screen.py", line 296, in initEPD
  File "/home/pi/src/epd_display/paperpi/waveshare_epd/epd2in7.py", line 222, in init
  File "/home/pi/src/epd_display/paperpi/waveshare_epd/epdconfig.py", line 74, in module_init
OSError: [Errno 24] Too many open files
Traceback (most recent call last):
  File "/usr/lib/python3.7/weakref.py", line 628, in _exitfunc
  File "/usr/lib/python3.7/weakref.py", line 552, in __call__
  File "/usr/lib/python3.7/tempfile.py", line 934, in _cleanup
  File "/usr/lib/python3.7/shutil.py", line 487, in rmtree
  File "/usr/lib/python3.7/shutil.py", line 485, in rmtree
OSError: [Errno 24] Too many open files: '/tmp/PaperPi_489piixc'

This appears to be a problem in the WaveShare epdconfig.py. The SPI handle is opened, but it is not closed anywhere after writing.

Putting the display to sleep does not close out the SPI handle.

Adding an self.SPI.close() call to the module_exit() method does not appear to help

    def module_exit(self):
        logging.debug("spi end")
        self.SPI.close()

        logging.debug("close 5V, Module enters 0 power consumption ...")
        self.GPIO.output(self.RST_PIN, 0)
        self.GPIO.output(self.DC_PIN, 0)

        self.GPIO.cleanup()
        self.SPI.close() # this does not appear to help
txoof commented 3 years ago

I have discovered the root of this problem: the module does clean up as expected.

It is critical that you keep track of every single init() call and follow it up with a sleep() call before doing any other init.

Switching to a with open() context might be a good way to prevent this type of untidy behavior in future updates.

txoof commented 3 years ago

I have a fix for this in development. All of the write/clear functions will be wrapped in an init/cleanup decorator.

txoof commented 3 years ago

Corrected in this commit.

SPI file handles should be closed appropriately in most cases though may remain open after a crash.