Ensure that converted args outlive call. Eliminate a race condition by ensuring that the refcount decrement of a converted argument does not happen until after the call into C completes.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/021f421e Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/021f421e Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/021f421e Branch: refs/heads/master Commit: 021f421e7e82a952af9e3c99698190910ccc3bef Parents: 0728625 Author: Marvin Humphrey <[email protected]> Authored: Tue Jul 14 12:08:58 2015 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Mon Jul 20 13:40:37 2015 -0700 ---------------------------------------------------------------------- compiler/src/CFCGoFunc.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/021f421e/compiler/src/CFCGoFunc.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCGoFunc.c b/compiler/src/CFCGoFunc.c index b9177b3..060e62b 100644 --- a/compiler/src/CFCGoFunc.c +++ b/compiler/src/CFCGoFunc.c @@ -70,6 +70,7 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass *invoker, } char *params = CFCUtil_strdup(""); + char *converted = CFCUtil_strdup(""); int start = targ == IS_METHOD ? 1 : 0; for (int i = start; param_vars[i] != NULL; i++) { CFCVariable *var = param_vars[i]; @@ -81,6 +82,26 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass *invoker, } params = CFCUtil_cat(params, go_name, " ", go_type_name, NULL); FREEMEM(go_type_name); + + // Convert certain types and defer their destruction until after the + // Clownfish call returns. + if (CFCType_is_string_type(type)) { + const char *cf_prefix = CFCParcel_is_cfish(parcel) + ? "" : "clownfish."; + char pattern[] = + "%s\t%sCF := C.cfish_Str_new_steal_utf8(" + "C.CString(%s), C.size_t(len(%s)))\n" + ; + char *temp = CFCUtil_sprintf(pattern, converted, go_name, go_name, + go_name, go_name); + FREEMEM(converted); + converted = temp; + if (!CFCType_decremented(type)) { + converted = CFCUtil_cat(converted, + "\tdefer C.cfish_dec_refcount(unsafe.Pointer(", go_name, + "CF))\n", NULL); + } + } } char *ret_type_str; @@ -96,11 +117,13 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass *invoker, char pattern[] = "func %s%s(%s) %s {\n" + "%s" ; - char *content - = CFCUtil_sprintf(pattern, invocant, name, params, ret_type_str); + char *content = CFCUtil_sprintf(pattern, invocant, name, params, + ret_type_str, converted); FREEMEM(invocant); + FREEMEM(converted); FREEMEM(params); FREEMEM(ret_type_str); return content; @@ -151,16 +174,7 @@ S_prep_cfargs(CFCParcel *parcel, CFCClass *invoker, // Don't convert a clownfish.String invocant. && (targ != IS_METHOD || i != 0) ) { - const char *format; - if (CFCParcel_is_cfish(parcel)) { - format = "%s((*C.cfish_String)(unsafe.Pointer(NewString(%s).TOPTR())))"; - } - else { - format = "%s((*C.cfish_String)(unsafe.Pointer(clownfish.NewString(%s).TOPTR())))"; - } - char *temp = CFCUtil_sprintf(format, cfargs, go_name); - FREEMEM(cfargs); - cfargs = temp; + cfargs = CFCUtil_cat(cfargs, go_name, "CF", NULL); } else if (CFCType_is_object(type)) {
