-
Notifications
You must be signed in to change notification settings - Fork 465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ObjectWrap destructor crashes node due to double napi delete calls #660
Comments
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660
I believe the problem is that we are not supposed to |
@addaleax an alternative fix occurred to me but its implications are much broader. The reason this crashes is that it does three(!) deletes on env teardown:
This is OK during gc because the In the case of env teardown the same thing happens as in the case of gc except the The broader question is whether this would break anybody. |
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660
Thanks for the fix. Tested with my own code and for now, no crashes. This seems to fix the crash :) |
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Kevin Eady <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs#660 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Kevin Eady <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs/node-addon-api#660 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Kevin Eady <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs/node-addon-api#660 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Kevin Eady <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs/node-addon-api#660 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Kevin Eady <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
`napi_remove_wrap()` was intended for objects that are alive for which the native addon wishes to withdraw its native pointer, and perhaps replace it with another. Therefore we need not `napi_remove_wrap()` during gc/env-cleanup. It is sufficient to `napi_delete_reference()`, as `Reference<Object>` already does. We need only `napi_remove_wrap()` if the construction failed and therefore no gc callback will ever happen. This change also removes references to `ObjectWrapConstructionContext` from the header because the class is not used anymore. Fixes: nodejs/node-addon-api#660 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Kevin Eady <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
Hi, using latest version from git, I'm getting crashes when node is closing about invalid access to memory or even double-free of the same pointer. I compiled node 13.7.0 with debug and asan to get a full report of the crash and that's the output: see gist.
For what I found running the debugger:
ObjectWrap
destructor runs the napi_remove_wrap function. This function calls another inside the NAPI which does not remove the reference yet, but sets a variable to true (see v8impl::Reference::Delete).ObjectWrap
inherits fromReference
, theReference
destructor calls the function napi_delete_reference, in which the NAPI internally runs again the sameDelete
function from before but this time deleting the object (see code).v8impl::Reference::Delete
should be called or not, but as the reference (this
) itself has been deleted already, asan complains and shows the above report (see code).I replicated the crash under 12.14.1 and 13.7.0 but not on 10.18.1 using the latest
master
code of this package (commit 4648420) all on macOS. The crash also replicates for any of the objects I create from JS which is a ObjectWrap.While doing some changes to try to avoid the crash, I come up with adding
this->SuppressDestruct();
when thenapi_remove_wrap
is called in theObjectWrap
destructor:I think this is the worst way to fix it, but at least I don't get crashes.
Edit: the call-to-
SuppressDestruct()
trick sometimes does not work if the constructor of the C++ object throws an exception.The text was updated successfully, but these errors were encountered: