Skip to content

Fix leak when returning BlockingIOError from a read - #143

Merged
gvalkov merged 1 commit into
gvalkov:masterfrom
jbleon95:master
Nov 5, 2020
Merged

Fix leak when returning BlockingIOError from a read #143
gvalkov merged 1 commit into
gvalkov:masterfrom
jbleon95:master

Conversation

@jbleon95

Copy link
Copy Markdown
Contributor

Discovered a leak related to the read method for an InputDevice, when it returns a BlockingIOError while there is nothing to read. Ultimately tracked it down to a reference counting bug in device_read_many in input.c. Was able to recreate it using the following script

import evdev
import objgraph
import select
import time

def test_device_read_leak(device_name):
    device = evdev.InputDevice(device_name)
    start_time = time.time()

    while time.time() - start_time < 30:
        r, _, _ = select.select([device.fd], [], [], 0.1)
        try:
            for event in device.read():
                pass
        except BlockingIOError:
            pass

print("Before loop calling device.read() ~300 times")
objgraph.show_growth()
test_device_read_leak('/dev/input/event2')
print("\nAfter loop")
objgraph.show_growth()

Results before change

Before loop calling device.read() ~300 times
function                       3411     +3411
dict                           1616     +1616
tuple                          1371     +1371
wrapper_descriptor             1059     +1059
weakref                        1037     +1037
builtin_function_or_method      848      +848
method_descriptor               834      +834
getset_descriptor               614      +614
type                            467      +467
list                            380      +380

After loop
list      679      +299

After change

Before loop calling device.read() ~300 times
function                       3411     +3411
dict                           1616     +1616
tuple                          1371     +1371
wrapper_descriptor             1059     +1059
weakref                        1037     +1037
builtin_function_or_method      848      +848
method_descriptor               834      +834
getset_descriptor               614      +614
type                            467      +467
list                            380      +380

After loop

@gvalkov
gvalkov merged commit 00c0fa7 into gvalkov:master Nov 5, 2020
@gvalkov

gvalkov commented Nov 5, 2020

Copy link
Copy Markdown
Owner

Excellent. Thanks for the fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants