[fetch] Fix memory leak inside saveResponseAndStatus in streaming mode#26273
[fetch] Fix memory leak inside saveResponseAndStatus in streaming mode#26273inolen wants to merge 1 commit intoemscripten-core:mainfrom
Conversation
|
The test there is weird - it's testing that data is NULL in onload which would indicate a leak, since data isn't free'd until Edit: to clarify, I think that assert() should be removed from the test, or else onprogress would need to become responsible for free'ing data before onload is called and before the user calls |
…ming mode when streaming was enabled - * onprogress allocated emscripten_fetch_t.data * onload called saveResponseAndStatus * xhr.response was NULL (due to streaming) which caused ptr to remain 0 * emscripten_fetch_t.data was uncondtionally overwritten by ptr, leaking what was allocated during onprogress
734c1aa to
05aa29a
Compare
| attr.onsuccess = [](emscripten_fetch_t *fetch) { | ||
| printf("Finished downloading %llu bytes\n", fetch->totalBytes); | ||
| printf("Data checksum: %08X\n", checksum); | ||
| assert(fetch->data == 0); // The data was streamed via onprogress, no bytes available here. |
There was a problem hiding this comment.
It seems like the idea is that with streaming you get the bytes only in the progress events and not in the onsuccess event.
At least that has been the way the API has been since this test was added 10 years ago: 786f2fe
There was a problem hiding this comment.
Yep, but the same structure (with the ->data pointer) is passed to both events. To keep the test as is, ->data would have to be free'd and NULL'd before calling onsuccess.
As I said in a previous reply, I think of ->data as the persistent buffer between events and ->numBytes as the amount of data in that buffer that's valid for the current event. ->numBytes being 0 is important, but ->data being required to be NULL in onload seems odd.
I think the idea is that with stream you get a series |
sbc100
left a comment
There was a problem hiding this comment.
Since ptr is initialized to emscripten_fetch_t.data and then used in realloc and then re-assigned to emscripten_fetch_t.data what is basically happening is like writing this in C:
f->data = realloc(f->data, newsize);
In this case there is no leak, right? Only the new f->data need be freed.
It's a bit hidden - xhr.response is NULL when streaming is used. In saveResponseAndStatus (called by onload), if response.xhr is NULL, the data pointer is set to NULL (at which point its leaked).
Absolutely. However, I think of |
|
I see, so if we want to keep the current API (with data NULL in onload under streaming) would need to call |
when streaming was enabled -
This change also wraps realloc in a guard to only call it if necessary (new buffer is larger than existing).
Not sure what's the best way to unobtrusively test this - is there some setting that enables some basic leak detections we could enable for an existing test that uses streaming (e.g. test_fetch_stream_async)?