kernel/port: Properly release the first reference to the Port object.

Creating a BReferenceable sets its reference count to 1.
create_port() was then acquiring 2 references for the two lists
it inserts the port object into, and subsequently delete_port()
releases those.

But that "reference 0" never was released anywhere, and so
despite being removed from hashes, etc. port objects were
just leaked, along with whatever messages remained in their
queue, never to be freed. This of course can add up pretty
quickly in systems that created and deleted ports frequently,
for instance, in long-running media playback, opening/closing
applications, etc.

As far as I can tell, this bug was introduced in the fix to
#8007 (7f64b301b1e78fb5a50c44a0cb2bb94a91e31d00), which introduced
the ref-counting system to the port heap, so it has been with us
since 2013 (!).

Fixes #15489, and probably some of the other "media playback
memory leak" tickets.
This commit is contained in:
Augustin Cavalier 2019-11-23 15:13:24 -05:00
parent 057719ef90
commit 072b9ed0ac

View File

@ -993,12 +993,12 @@ create_port(int32 queueLength, const char* name)
name != NULL ? name : "unnamed port");
if (port == NULL)
return B_NO_MEMORY;
BReference<Port> portRef(port, true);
// check the ports limit
const int32 previouslyUsed = atomic_add(&sUsedPorts, 1);
if (previouslyUsed + 1 >= sMaxPorts) {
atomic_add(&sUsedPorts, -1);
delete port;
return B_NO_MORE_PORTS;
}