diff options
| author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2026-06-23 11:44:18 +0400 |
|---|---|---|
| committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2026-06-24 15:41:14 +0400 |
| commit | 0457762e9e08be216567c33ca89ce7523a1213ba (patch) | |
| tree | 4b570080187a5507ca90011f1a5027f6fac5a82e /system | |
| parent | 5cac1d9c9394e633402ebe82e7ab1871b3ae2379 (diff) | |
| download | qemu-0457762e9e08be216567c33ca89ce7523a1213ba.tar.gz qemu-0457762e9e08be216567c33ca89ce7523a1213ba.zip | |
irq: add per-IRQ observer to fix qemu_irq_intercept_in leak
qemu_irq_intercept_in() saves original IRQ handlers by allocating
new QOM objects, which are never freed. On a PC machine, this leaks
IRQ objects (one per IOAPIC pin) on every qtest run.
Rather than tracking allocations to free later, avoid them: add an
"observer" field to IRQState, called by qemu_set_irq() after the
real handler. Interception sets the observer instead of rewriting
handlers, so there's nothing to save and nothing to leak.
Fix qemu_notirq() to route through qemu_set_irq() so inverted IRQs
trigger observers too. Drop the LSan suppression.
Reviewed-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260623-b4-ui-v4-3-4656aec3398d@redhat.com>
Diffstat (limited to 'system')
| -rw-r--r-- | system/qtest.c | 5 |
1 files changed, 1 insertions, 4 deletions
diff --git a/system/qtest.c b/system/qtest.c index fd37bcbfaa..cf30123917 100644 --- a/system/qtest.c +++ b/system/qtest.c @@ -326,9 +326,6 @@ void qtest_sendf(CharFrontend *chr, const char *fmt, ...) static void qtest_irq_handler(void *opaque, int n, int level) { - qemu_irq old_irq = *(qemu_irq *)opaque; - qemu_set_irq(old_irq, level); - if (irq_levels[n] != level) { CharFrontend *chr = &qtest->qtest_chr; irq_levels[n] = level; @@ -421,7 +418,7 @@ static void qtest_process_command(CharFrontend *chr, gchar **words) interception_succeeded = true; } } else { - qemu_irq_intercept_in(ngl->in, qtest_irq_handler, + qemu_irq_set_observer(ngl->in, qtest_irq_handler, ngl->num_in); interception_succeeded = true; } |
