hyperledger / indy-vdr

A library and proxy server for interacting with Hyperledger Indy Node ledger instances
Apache License 2.0
54 stars 71 forks source link

Memory leak in the javascript wrapper #317

Open jens-mp opened 3 months ago

jens-mp commented 3 months ago

Using the javascript wrapper to request the validator info data from every node in a network seems to leak memory. We saw this behavior consistently in our backend service over several weeks now.

To pin down the problem, we stripped down our backend service to a very minimal version and pushed it here: https://github.com/jens-mp/indy-network-monitor/blob/main/backend/src/server.ts. Essentially it's an endless loop which creates a new GetValidatorInfoAction, signs it and sends it to the network every 60 seconds. Additionally memory statistics are printed.

The program ran for about 10 days and during this period the heap usage of node was always below 8 megabyte. So the used up memory should not be within the javascript land. But the memory used by the process (rss) increased constantly up to around 1 gigabyte. Per request to the network the response size is around 102 kilobyte and the rss increases per request by around 110 kilobyte (on average over 9 days). This might be a hint, that the response data is still present in the wrapper or the rust library.

jens-mp commented 3 months ago

After further investigation of the wrapper's source code we have a hypothesis for the memory leak.

The response to the validator info request is transformed to a C string with rust_string_to_c() in pool.rs line 306 and handed over to the ffi consumer. The javascript wrapper transforms the respone into an object with JSON.parse() in NodeJSIndyVdr.ts line 98. But nowhere in the javascript wrapper code the C string is freed with the help of indy_vdr_string_free(). So we assume this is the problem and NodeJSIndyVdr.ts line 98 should rather look something like this.

          const obj = JSON.parse(mappedResponse) as Return
          indy_vdr_string_free(response)
          resolve(obj)

But indy_vdr_string_free() is currently not listed in the functions used by the wrapper.

jens-mp commented 3 months ago

We patched the javascript wrapper locally and added indy_vdr_string_free() to test our hypothesis.

Calling indy_vdr_string_free() leads to crashes because of invalid frees.