MobileDev360
The NIF resource is destroyed if you put it in the ETS table
Hi,
I’am trying to make a NIF resource and put it in the ETS, but the resource is destroyed just immediate after I have put it in ETS. Maybe someone knows what’s the matter?
For example:
iex(43)> :ets.insert :test, {5, TupleNif.tuple_to_binary({1, 2, 3})}
Destructing array: 0x14042ed0
TupleNif.tuple_to_binary({1, 2, 3} - create NIF resource.
I am added the debug output in the resource destroying NIF function, so as we can see the debug output “Destructing array: 0x14042ed0” indicates that the resource is destroyed.
iex(44)> [{k, v}] = :ets.lookup :test, 5
[{5, #Reference<0.2003688078.3595960321.242503>}]
iex(45)> TupleNif.binary_to_tuple v
Bug Bug ..!!** (ArgumentError) argument error
In the TupleNif.binary_to_tuple NIF function the ArgumentError returned if we can’t get resource from the input parameter.
OTP21
Most Liked
MobileDev360
It seems you are right.
When we pass the created resource to the ETS, probably Erlang take over ownership of the resource by copying resource memory block to new place and calling resource destructor we pass to the enif_open_resource_type for the old resource memory block.
It looks like, when inserting user data into ETS, all data is copied into a special block of memory allocated for ETS and memory of user data is deallocated. Probably, ETS has its own memory block to save ETS data to disk via tab2file quickly.
Thanks!
Qqwy
While not the root cause of your problem, I expect that it is not possible to store structures with pointers inside ETS (but only fully ‘flat’ data), because how would the system otherwise be able to keep track of the pointers and the memory it pointed towards?
garazdawi
It should be perfectly fine to insert nif resources into ETS tables. Most likely you have done something wrong with the refc of the resources in the nif. What happens if you just call a garbage collection instead of inserting the resource into the etc table?
MobileDev360
If to save the resource to a variable, then everything is fine. We can call garbage collection any times but while the variable is somehow used the resource destructor not called. If we also insert the resource to ETS, everything is fine too. But if we do not assign the resource to a variable and insert it to ETS, then the resource will be destroyed.
In the NIF I have created the resource next way:
Array* array = enif_alloc_resource(array_type, sizeof(Array));
... filling array with data...
ERL_NIF_TERM term = enif_make_resource(env, array);
enif_release_resource(array);
return term;
If to comment the enif_release_resource(array); than a hanging reference to resource will appear and it will not be removed in case of inserting it to ETS but of course this is just experiment.







