Changeset: dce7fa42e62a for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=dce7fa42e62a
Modified Files:
        sql/backends/monet5/UDF/capi/Tests/capi04.sql
        sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
        sql/backends/monet5/UDF/capi/capi.c
Branch: jitudf
Log Message:

Automatically clean up any mallocs performed in the jitted function.


diffs (190 lines):

diff --git a/sql/backends/monet5/UDF/capi/Tests/capi04.sql 
b/sql/backends/monet5/UDF/capi/Tests/capi04.sql
--- a/sql/backends/monet5/UDF/capi/Tests/capi04.sql
+++ b/sql/backends/monet5/UDF/capi/Tests/capi04.sql
@@ -10,8 +10,6 @@ CREATE FUNCTION capi04(inp STRING) RETUR
                if (inp.is_null(inp.data[i])) {
                        result->data[i] = result->null_value;
                } else {
-                       // the contract says we must use "malloc" to allocate 
for the result strings
-                       // "malloc" is a function pointer that actually points 
to GDKmalloc
                        result->data[i] = malloc(strlen(inp.data[i]) + 2);
                        strcpy(result->data[i] + 1, inp.data[i]);
                        result->data[i][0] = 'H';
@@ -35,8 +33,28 @@ CREATE FUNCTION capi04(inp STRING) RETUR
 };
 
 SELECT capi04(i) FROM strings;
+ROLLBACK;
+
+START TRANSACTION;
+# return constant strings, instead of allocated strings
+CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
+#include <string.h>
+
+       result->initialize(result, inp.count);
+       for(size_t i = 0; i < inp.count; i++) {
+               if (inp.is_null(inp.data[i])) {
+                       result->data[i] = result->null_value;
+               } else {
+                       result->data[i] = malloc(strlen(inp.data[i]) + 2);
+                       strcpy(result->data[i] + 1, inp.data[i]);
+                       result->data[i] = "hello";
+               }
+       }
+};
+
+CREATE TABLE strings(i STRING);
+INSERT INTO strings VALUES ('ello'), ('ow'), (NULL), ('onestly?'), ('annes');
+
+SELECT capi04(i) FROM strings;
 
 ROLLBACK;
-
-
-
diff --git a/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out 
b/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
--- a/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
+++ b/sql/backends/monet5/UDF/capi/Tests/capi04.stable.out
@@ -54,14 +54,10 @@ Ready.
 # loading sql script: 90_generator.sql
 # loading sql script: 90_generator_hge.sql
 # loading sql script: 99_system.sql
-Hello
-How
-Honestly?
-Hannes
 
-# 15:50:30 >  
-# 15:50:30 >  "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" 
"--host=/var/tmp/mtest-20003" "--port=32751"
-# 15:50:30 >  
+# 12:56:26 >  
+# 12:56:26 >  "mclient" "-lsql" "-ftest" "-Eutf-8" "-i" "-e" 
"--host=/var/tmp/mtest-37150" "--port=31836"
+# 12:56:26 >  
 
 #START TRANSACTION;
 #CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
@@ -98,6 +94,35 @@ Hannes
 #      }
 #};
 #ROLLBACK;
+#START TRANSACTION;
+#CREATE FUNCTION capi04(inp STRING) RETURNS STRING LANGUAGE C {
+##include <string.h>
+#
+#      result->initialize(result, inp.count);
+#      for(size_t i = 0; i < inp.count; i++) {
+#              if (inp.is_null(inp.data[i])) {
+#                      result->data[i] = result->null_value;
+#              } else {
+#                      result->data[i] = malloc(strlen(inp.data[i]) + 2);
+#                      strcpy(result->data[i] + 1, inp.data[i]);
+#                      result->data[i] = "hello";
+#              }
+#      }
+#};
+#CREATE TABLE strings(i STRING);
+#INSERT INTO strings VALUES ('ello'), ('ow'), (NULL), ('onestly?'), ('annes');
+[ 5    ]
+#SELECT capi04(i) FROM strings;
+% sys.L2 # table_name
+% L2 # name
+% clob # type
+% 5 # length
+[ "hello"      ]
+[ "hello"      ]
+[ NULL ]
+[ "hello"      ]
+[ "hello"      ]
+#ROLLBACK;
 
 # 15:50:31 >  
 # 15:50:31 >  "Done."
diff --git a/sql/backends/monet5/UDF/capi/capi.c 
b/sql/backends/monet5/UDF/capi/capi.c
--- a/sql/backends/monet5/UDF/capi/capi.c
+++ b/sql/backends/monet5/UDF/capi/capi.c
@@ -22,6 +22,13 @@
 #include <unistd.h>
 #include <string.h>
 
+struct _allocated_region;
+typedef struct _allocated_region {
+       struct _allocated_region* next;
+} allocated_region;
+
+
+static __thread allocated_region* allocated_regions;
 static __thread jmp_buf jump_buffer;
 
 static str
@@ -125,7 +132,7 @@ clear_mprotect(void* addr, size_t len) {
        }
 
 
-static void* wrapped_GDK_malloc(size_t size) {
+static void* jump_GDK_malloc(size_t size) {
        void* ptr = GDKmalloc(size);
        if (!ptr) {
                longjmp(jump_buffer, 2);
@@ -133,11 +140,21 @@ static void* wrapped_GDK_malloc(size_t s
        return ptr;
 }
 
+static void* wrapped_GDK_malloc(size_t size) {
+       allocated_region* region;
+       void* ptr = jump_GDK_malloc(size + sizeof(allocated_region));
+       region = (allocated_region*)ptr;
+       region->next = allocated_regions;
+       allocated_regions = region;
+       
+       return ptr + sizeof(allocated_region);
+}
+
 #define GENERATE_BASE_HEADERS(type, tpename) \
 static int tpename##_is_null(type value); \
 static void tpename##_initialize(struct cudf_data_struct_##tpename* self, 
size_t count) { \
        self->count = count; \
-       self->data = wrapped_GDK_malloc(count * sizeof(self->null_value)); \
+       self->data = jump_GDK_malloc(count * sizeof(self->null_value)); \
 }
 
 #define GENERATE_BASE_FUNCTIONS(tpe, tpename) \
@@ -278,6 +295,8 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
 
        (void) cntxt;
 
+       allocated_regions = NULL;
+
        // we need to be able to catch segfaults and bus errors
        // so we can work with mprotect to prevent UDFs from changing
        // the input data
@@ -781,7 +800,7 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
                        goto wrapup;
                } else {
                        // we jumped here
-                       msg = createException(MAL, "cudf.eval", "We longjumped 
here because of an error!.");
+                       msg = createException(MAL, "cudf.eval", "We longjumped 
here because of an error, but we don't know which!");
                        goto wrapup;
                }
        }
@@ -903,9 +922,6 @@ CUDFeval(Client cntxt, MalBlkPtr mb, Mal
                                        msg = createException(MAL, "cudf.eval", 
MAL_MALLOC_FAIL);
                                        goto wrapup;
                                }
-                               if (ptr != str_nil) {
-                                       GDKfree(source_base[j]);
-                               }
                        }
                        GDKfree(data);
                } else {
@@ -940,6 +956,11 @@ wrapup:
                GDKfree(regions);
                regions = next;
        }
+       while(allocated_regions) {
+               allocated_region* next = allocated_regions->next;
+               GDKfree(allocated_regions);
+               allocated_regions = next;
+       }
        // block segfaults and bus errors again after we exit
        (void) pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
        // argument names (input)
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to