raspberrypi / picamera2

New libcamera based python library
BSD 2-Clause "Simplified" License
852 stars 180 forks source link

[BUG] Memory Leak when reinitializing Picamera2 with new camera_num, results in OSError: [Errno 12] Cannot allocate memory #958

Open why-myles opened 7 months ago

why-myles commented 7 months ago

Describe the bug Every time I initialize Picamera2 with a new camera_num, more memory seems taken by the Picamera2 object. Eventually the system runs out of memory and I get a OSError: [Errno 12] Cannot allocate memory error.

To Reproduce

from picamera2 import Picamera2, Preview
import time

while True:
    for i in range(1):
        picam2 = Picamera2(camera_num=i)
        picam2.start_preview(Preview.NULL)
        picam2.start()
        picam2.capture_file("device/runtime/picture.jpg")
        picam2.close()
    time.sleep(0.1)

Expected behaviour Expected that this script could run forever without an error.

Console Output, Screenshots

Traceback (most recent call last):
  File "/home/myles/dev/zeebo/device/picam2_memoryleak.py", line 8, in <module>
    picam2.start()
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1149, in start
    self.configure(config)
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1104, in configure
    self.configure_(camera_config)
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 1087, in configure_
    self.allocator.allocate(libcamera_config)
  File "/usr/lib/python3/dist-packages/picamera2/allocators/dmaallocator.py", line 43, in allocate
    fd = self.dmaHeap.alloc(f"picamera2-{i}", stream_config.frame_size)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/picamera2/dma_heap.py", line 98, in alloc
    ret = fcntl.ioctl(self.__dmaHeapHandle.get(), DMA_HEAP_IOCTL_ALLOC, alloc)

Hardware : RPi 4. Gen3 wide angle and Gen2 camera connected to an Arducam Camera Board V2.2

Additional context

davidplowman commented 7 months ago

Thanks for reporting this. Running the latest versions of the software, we think it's actually leaking a file descriptor rather than memory and are working on a fix.

davidplowman commented 7 months ago

Should be fixed by: https://github.com/raspberrypi/picamera2/pull/960

simonsci commented 6 months ago

RPi4, Arducam 64MP Still facing the exact same issue like above.

davidplowman commented 6 months ago

RPi4, Arducam 64MP Still facing the exact same issue like above.

Hi, can you confirm what version of Picamera2 you are running. Please confirm your OS version (cat /etc/os-release), kernel version (uname -a) and the amount of CMA you have (grep Cma /proc/meminfo). Also, how much RAM does your Pi have? Finally, please attach the smallest and simplest script that you can that will reproduce the problem you are having. Thanks.

simonsci commented 6 months ago

Hi, thx for the fast response.

  1. git head is c4d6aab91013c6a5567297b8643c87692fb1f1bc of the next branch

  2. PRETTY_NAME="Debian GNU/Linux 12 (bookworm)" NAME="Debian GNU/Linux" VERSION_ID="12" VERSION="12 (bookworm)" VERSION_CODENAME=bookworm ID=debian HOME_URL="https://www.debian.org/" SUPPORT_URL="https://www.debian.org/support" BUG_REPORT_URL="https://bugs.debian.org/"

  3. Linux fotobox 6.1.0-rpi7-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.63-1+rpt1 (2023-11-24) aarch64 GNU/Linux

  4. CmaTotal: 524288 kB CmaFree: 474212 kB

  5. RPI4B-4GB

import sys sys.path.append('/home/pi/fotobox/picamera2') from picamera2 import Picamera2, Preview from libcamera import Transform import time

for i in range(10): picam2 = Picamera2()

preview_config = picam2.create_preview_configuration(main={"size": (3840, 2160)})
picam2.configure(preview_config)
picam2.set_controls({"AfMode": 2 ,"AfTrigger": 0})

picam2.start_preview(Preview.QTGL, x=0, y=0, width=1920, height=1080, transform=Transform(hflip=1))

picam2.start()
picam2.capture_file("test.jpg")
time.sleep(2)
picam2.stop_preview()
picam2.close()
time.sleep(2)

After two runs, error of above occurs

davidplowman commented 6 months ago

Thanks for the clarification. Yes, I can reproduce that. Is this a new failure, or has it always been like this, do you know? Thanks.

simonsci commented 6 months ago

The first time i used picamera2 was by the end of december 23

davidplowman commented 6 months ago

The problem is related to closing down the QTGL preview window (the non-GL Qt version, as well as the DRM version, are all fine). EGL (or someone) appears to hold onto to references to image buffers for reasons I don't understand. TBH I'm not sure if it's always done this, or if it's a new "feature", I'm slightly suspecting the latter. I'll have to find someone who know about the 3D graphics stack and how it uses Linux dmabufs.

In the meantime the only workaround I have is to avoid closing that preview window. If you can start the camera only once per process then you can configure, re-configure, start, stop the camera as often as you like.

davidplowman commented 6 months ago

You could try this PR: https://github.com/raspberrypi/picamera2/pull/981

I did find something after rooting around in some stuff I have no understanding of!

simonsci commented 6 months ago

Yeah, it works! Thank you so much!!!

davidplowman commented 6 months ago

Great, I'll merge that onto next then, and it'll appear in the next release (for those who don't want to install pre-release versions from the next branch).