From 3e00abf31835100305566d7d6288f3153e4769a4 Mon Sep 17 00:00:00 2001 From: John Haley Date: Tue, 24 Feb 2015 09:29:29 -0700 Subject: [PATCH] Allow for saving of props to an object Some properties were being set on the libgit2 C struct but would be destroyed after the function is completed. The problem was that C struct would still assume that the memory it had was valid and would try to use it resulting in random segfaults. Now you can mark an argument as `saveArg` and then that argument will be persisted to the parent object and disposed of when the parent is deleted. Currently this only works in sync functions since I couldn't find an async method that would need this. If this changes it shouldn't be too hard to implement. Another thing to note is that the if the parent object is marked as `!selfFreeing` then we're still going to dispose of the persisted objects because if not then they will memory leak all over the place. This might need to be looked into more later. I currently couldn't find a situation where this would happen but the code is pretty complicated at this point and I certainly could have missed something --- generate/input/descriptor.json | 7 ++++++ generate/templates/partials/sync_function.cc | 12 +++++++++ generate/templates/templates/class_content.cc | 25 +++++++++++++++++++ generate/templates/templates/class_header.h | 14 +++++++++++ 4 files changed, 58 insertions(+) diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index 460b7fba2..c7df8dfb2 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -1348,6 +1348,13 @@ "git_remote_rename": { "ignore": true }, + "git_remote_set_callbacks": { + "args": { + "callbacks": { + "saveArg": true + } + } + }, "git_remote_set_fetch_refspecs": { "ignore": true }, diff --git a/generate/templates/partials/sync_function.cc b/generate/templates/partials/sync_function.cc index 16b0aa3dc..452e02920 100644 --- a/generate/templates/partials/sync_function.cc +++ b/generate/templates/partials/sync_function.cc @@ -18,6 +18,18 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { {%if not arg.isCallbackFunction %} {%if not arg.payloadFor %} {%partial convertFromV8 arg %} + {%if arg.saveArg %} + Persistent {{ arg.name }}; + Handle {{ arg.name }}Handle(args[{{ arg.jsArg }}]->ToObject()); + NanAssignPersistent({{ arg.name }}, {{ arg.name }}Handle); + {{ cppClassName }} *thisObj = ObjectWrap::Unwrap<{{ cppClassName }}>(args.This()); + + if (thisObj->{{ cppFunctionName }}_{{ arg.name }} != NULL) { + NanDisposePersistent(*thisObj->{{ cppFunctionName }}_{{ arg.name }}); + } + + thisObj->{{ cppFunctionName }}_{{ arg.name }} = &{{ arg.name }}; + {%endif%} {%endif%} {%endif%} {%endif%} diff --git a/generate/templates/templates/class_content.cc b/generate/templates/templates/class_content.cc index 5efa227af..3a7abddbb 100644 --- a/generate/templates/templates/class_content.cc +++ b/generate/templates/templates/class_content.cc @@ -29,6 +29,16 @@ using namespace node; {{ cppClassName }}::{{ cppClassName }}({{ cType }} *raw, bool selfFreeing) { this->raw = raw; this->selfFreeing = selfFreeing; + + {% each functions as function %} + {% if not function.ignore %} + {% each function.args as arg %} + {% if arg.saveArg %} + {{ function.cppFunctionName }}_{{ arg.name }} = NULL; + {% endif %} + {% endeach %} + {% endif %} + {% endeach %} } {{ cppClassName }}::~{{ cppClassName }}() { @@ -37,6 +47,21 @@ using namespace node; {{ freeFunctionName }}(this->raw); } {% endif %} + + // this will cause an error if you have a non-self-freeing object that also needs + // to save values. Since the object that will eventually free the object has no + // way of knowing to free these values. + {% each function as function %} + {% if not function.ignore %} + {% each function.args as arg %} + {% if arg.saveArg %} + if ({{ function.cppFunctionName }}_{{ arg.name }} != NULL) { + NanDisposePersistent(&{{ function.cppFunctionName }}_{{ arg.name }}); + } + {% endif %} + {% endeach %} + {% endif %} + {% endeach %} } void {{ cppClassName }}::InitializeComponent(Handle target) { diff --git a/generate/templates/templates/class_header.h b/generate/templates/templates/class_header.h index 1f4e18aba..74e711a1e 100644 --- a/generate/templates/templates/class_header.h +++ b/generate/templates/templates/class_header.h @@ -73,12 +73,26 @@ class {{ cppClassName }} : public ObjectWrap { {% endeach %} {% endif %} {% endeach %} + + private: + + {%if cType%} {{ cppClassName }}({{ cType }} *raw, bool selfFreeing); ~{{ cppClassName }}(); {%endif%} + {% each functions as function %} + {% if not function.ignore %} + {% each function.args as arg %} + {% if arg.saveArg %} + Persistent *{{ function.cppFunctionName }}_{{ arg.name }}; + {% endif %} + {% endeach %} + {% endif %} + {% endeach %} + static NAN_METHOD(JSNewFunction); {%each fields as field%}