#1105837 fwupd: Memory usage grows unbounded forever (memory leak)

Package:
fwupd
Source:
fwupd
Description:
Firmware update daemon
Submitter:
Phil Dibowitz
Date:
2025-07-11 23:35:01 UTC
Severity:
normal
#1105837#5
Date:
2025-05-15 22:26:21 UTC
From:
To:
Dear Maintainer,

I kept noticing very high memory usage on my desktop and tracked it down
to fwupd. I now restart fwupd every week or so to keep it from using all
RAM.

Currently it's only been running 2 days and it's got 6.9G resident, 7.5G
virtual, and 10.9% of memory, and is the top memory user, according to top:

```
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
2321320 root      20   0 7504636   6.9g  36732 S   0.0  10.9  27:51.60 fwupd
```

But after restarting, it's using a small 0.1% of my memory at 47k
resident and 370k virtual:

```
3563598 root      20   0  369384  47320  36136 S   0.0   0.1   0:00.75 fwupd
```

This definitely didn't used to happen, so I presume it's a recent
update.

#1105837#10
Date:
2025-05-16 04:51:03 UTC
From:
To:
Can you check fwupd.service for any errors that coincide with the higher
memory usage?

Also; any bad USB devices or kernel errors? There are some bug reports
that talked about descriptors getting left open when there was a bad USB
device.

We might need to try to use valgrind to find this problem.  You can try
to run valgrind like this:

|sudo valgrind --leak-check=full --show-leak-kinds=definite
/usr/libexec/fwupd/fwupd | tee fwupd.log
|

You can leave that running a few hours and then ctrl-c and share
fwupd.log and we'll see if anything stands out.

#1105837#15
Date:
2025-07-11 18:40:09 UTC
From:
To:
The only errors in the service are on startup:

Jul 09 00:00:04 rider fwupd[3253786]: 07:00:04.331 FuEngine
failed to add device
/sys/devices/pci0000:00/0000:00:01.2/0000:01:00.1/ata3/host2/target2:0:0/2:0:0:0/block/sr0:
failed to subclass open: failed to open /dev/sr0: Operation not permitted
Jul 09 00:00:04 rider fwupd[3253786]: 07:00:04.335 FuEngine
failed to add device
/sys/devices/pci0000:00/0000:00:01.2/0000:01:00.1/ata3/host2/target2:0:0/2:0:0:0/block/sr0:
failed to subclass open: failed to open /dev/sr0: Operation not permitted
Jul 09 00:00:04 rider fwupd[3253786]: 07:00:04.337 FuEngine
failed to add device
/sys/devices/pci0000:00/0000:00:03.1/0000:06:00.0/0000:07:00.0/0000:08:00.0:
failed to setup: cannot parse datastream

I'll run it under valgrind for a bit and get back to you with the log.

#1105837#20
Date:
2025-07-11 23:33:52 UTC
From:
To:
Fortunately valgrind's output is minimal because it turns out it writes
to stderr, not stdout, so that `tee` didn't get it. :)

Here's the output from about 5 hours.

# valgrind --leak-check=full --show-leak-kinds=definite
/usr/libexec/fwupd/fwupd | tee fwupd.log
==4003007== Memcheck, a memory error detector
==4003007== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==4003007== Using Valgrind-3.24.0 and LibVEX; rerun with -h for
copyright info
==4003007== Command: /usr/libexec/fwupd/fwupd
==4003007==
18:40:06.855 FuEngine             failed to add device
/sys/devices/pci0000:00/0000:00:01.2/0000:01:00.1/ata3/host2/target2:0:0/2:0:0:0/block/sr0:
failed to subclass open: failed to open /dev/sr0: No medium found
18:40:07.126 FuEngine             failed to add device
/sys/devices/pci0000:00/0000:00:01.2/0000:01:00.1/ata3/host2/target2:0:0/2:0:0:0/block/sr0:
failed to subclass open: failed to open /dev/sr0: No medium found
18:40:07.173 FuEngine             failed to add device
/sys/devices/pci0000:00/0000:00:03.1/0000:06:00.0/0000:07:00.0/0000:08:00.0:
failed to setup: cannot parse datastream
18:40:08.010 FuEngine             failed to add device
/sys/devices/virtual/msr/msr0: failed to add device using on msr: could
not read IA32_DEBUG_INTERFACE: failed to read from port 0x0c80:
Input/output error
18:40:08.257 FuMain               fwupd 2.0.8 ready for requests (locale
en_US.UTF-8)
^C==4003007==
==4003007== Process terminating with default action of signal 2 (SIGINT)
==4003007==    at 0x52EC9EE: __syscall_cancel_arch (syscall_cancel.S:56)
==4003007==    by 0x52E1667: __internal_syscall_cancel (cancellation.c:49)
==4003007==    by 0x52E16AC: __syscall_cancel (cancellation.c:75)
==4003007==    by 0x5355E6D: ppoll (ppoll.c:42)
==4003007==    by 0x512E64B: ??? (in
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8400.1)
==4003007==    by 0x512EFDE: g_main_loop_run (in
/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8400.1)
==4003007==    by 0x112E0A: fu_daemon_start (in /usr/libexec/fwupd/fwupd)
==4003007==    by 0x1114AC: main (in /usr/libexec/fwupd/fwupd)
==4003007==
==4003007== HEAP SUMMARY:
==4003007==     in use at exit: 174,650,598 bytes in 2,906,181 blocks
==4003007==   total heap usage: 30,350,893 allocs, 27,444,712 frees,
15,310,784,886 bytes allocated
==4003007==
==4003007== LEAK SUMMARY:
==4003007==    definitely lost: 0 bytes in 0 blocks
==4003007==    indirectly lost: 0 bytes in 0 blocks
==4003007==      possibly lost: 2,412,855 bytes in 625 blocks
==4003007==    still reachable: 131,036,687 bytes in 2,751,216 blocks
==4003007==                       of which reachable via heuristic:
==4003007==                         length64           : 262,920 bytes
in 340 blocks
==4003007==         suppressed: 0 bytes in 0 blocks
==4003007== Reachable blocks (those to which a pointer was found) are
not shown.
==4003007== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4003007==
==4003007== For lists of detected and suppressed errors, rerun with: -s
==4003007== ERROR SUMMARY: 80 errors from 80 contexts (suppressed: 0 from 0)