Commit 9d710be
committed
Avoid leaking uv_async_t in Dispatcher::Deactivate()
On disconnect, Dispatcher::Deactivate() calls uv_close() to close its
active uv_async_t instance and nulls out the corresponding field,
but never frees the underlying memory.
To reproduce, run the following with node-rdkafka and librdkafka
compiled with ASAN:
```js
const { KafkaConsumer } = require('../');
const consumer = new KafkaConsumer({
'group.id': 'kafka',
'metadata.broker.list': 'localhost:9092',
}, {});
consumer.connect({ timeout: 2000 }, function (err) {
if (err) {
console.error('Error connecting to Kafka:', err);
return;
}
consumer.disconnect();
})
```
This should report:
```
Direct leak of 128 byte(s) in 1 object(s) allocated from:
#0 0x7f049c3aa647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
Blizzard#1 0x7f0471d872a1 in NodeKafka::Callbacks::Dispatcher::Activate() ../src/callbacks.cc:69
Blizzard#2 0x7f0471e75c06 in NodeKafka::Workers::KafkaConsumerConnect::HandleOKCallback() ../src/workers.cc:579
Blizzard#3 0x7f0471dd679c in Nan::AsyncWorker::WorkComplete() ../node_modules/nan/nan.h:2008
Blizzard#4 0x7f0471dd679c in Nan::AsyncExecuteComplete(uv_work_s*) ../node_modules/nan/nan.h:2365
Blizzard#5 0x7f0471dd679c in Nan::AsyncExecuteComplete(uv_work_s*, int) ../node_modules/nan/nan.h:2369
Blizzard#6 0x18bb75c in uv__work_done ../deps/uv/src/threadpool.c:329
Blizzard#7 0x18bf0b2 in uv__async_io ../deps/uv/src/unix/async.c:176
Blizzard#8 0x18d3b2a in uv__io_poll ../deps/uv/src/unix/linux.c:1485
Blizzard#9 0x18bfdd6 in uv_run ../deps/uv/src/unix/core.c:447
Blizzard#10 0xbc9be5 in node::SpinEventLoopInternal(node::Environment*) (/usr/bin/node+0xbc9be5)
Blizzard#11 0xd1d920 in node::NodeMainInstance::Run(node::ExitCode*, node::Environment*) [clone .part.0] (/usr/bin/node+0xd1d920)
Blizzard#12 0xd1e38c in node::NodeMainInstance::Run() (/usr/bin/node+0xd1e38c)
Blizzard#13 0xc710be in node::Start(int, char**) (/usr/bin/node+0xc710be)
Blizzard#14 0x7f049bdf0d09 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x23d09)
```
The [libuv documentation](https://docs.libuv.org/en/v1.x/handle.html#c.uv_close)
says it's only safe to free the underlying memory in a close callback
passed to uv_close(), or after such a callback has returned. So, use a
unique_ptr with a custom deleter to accomplish this.1 parent 24e6e0c commit 9d710be
2 files changed
+21
-10
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
51 | | - | |
52 | | - | |
| 51 | + | |
53 | 52 | | |
54 | 53 | | |
55 | 54 | | |
| |||
66 | 65 | | |
67 | 66 | | |
68 | 67 | | |
69 | | - | |
70 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
79 | | - | |
80 | | - | |
81 | | - | |
| 78 | + | |
82 | 79 | | |
83 | 80 | | |
84 | 81 | | |
| |||
87 | 84 | | |
88 | 85 | | |
89 | 86 | | |
90 | | - | |
| 87 | + | |
91 | 88 | | |
92 | 89 | | |
93 | 90 | | |
| |||
119 | 116 | | |
120 | 117 | | |
121 | 118 | | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
122 | 130 | | |
123 | 131 | | |
124 | 132 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
49 | 50 | | |
50 | 51 | | |
51 | 52 | | |
52 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
53 | 56 | | |
54 | 57 | | |
55 | 58 | | |
| |||
0 commit comments