Changeset: 85fc1cd7c486 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=85fc1cd7c486
Modified Files:
        sql/backends/monet5/UDF/capi/capi.c
Branch: Mar2018
Log Message:

Make mprotect and longjmp on malloc failure optional in CUDFs.

If mprotect is disabled (default), input columns are always copied instead of 
protected from writing, allowing the user to safely write to them.
If longjmp on malloc failure is disabled (default), mallocs must be manually 
checked inside the CUDF.


diffs (252 lines):

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
@@ -23,6 +23,11 @@
 #pragma GCC diagnostic ignored "-Wclobbered"
 #endif
 
+const char *mprotect_enableflag = "enable_mprotect";
+static bool option_enable_mprotect = false;
+const char *longjmp_enableflag = "enable_longjmp";
+static bool option_enable_longjmp = false;
+
 struct _allocated_region;
 typedef struct _allocated_region {
        struct _allocated_region *next;
@@ -80,6 +85,8 @@ str CUDFprelude(void *ret)
        if (!cudf_initialized) {
                MT_lock_init(&cache_lock, "cache_lock");
                cudf_initialized = true;
+               option_enable_mprotect = GDKgetenv_istrue(mprotect_enableflag) 
|| GDKgetenv_isyes(mprotect_enableflag);
+               option_enable_longjmp = GDKgetenv_istrue(longjmp_enableflag) || 
GDKgetenv_isyes(longjmp_enableflag);
        }
        return MAL_SUCCEED;
 }
@@ -107,6 +114,7 @@ static void handler(int sig, siginfo_t *
 }
 
 static bool can_mprotect_region(void* addr) {
+       if (!option_enable_mprotect) return false;
        int pagesize = getpagesize();
        void* page_begin = (void *)((size_t)addr - (size_t)addr % pagesize);
        return page_begin == addr;
@@ -160,7 +168,7 @@ static char *clear_mprotect(void *addr, 
 static void *jump_GDK_malloc(size_t size)
 {
        void *ptr = GDKmalloc(size);
-       if (!ptr) {
+       if (!ptr && option_enable_longjmp) {
                longjmp(jump_buffer[THRgettid()], 2);
        }
        return ptr;
@@ -211,7 +219,8 @@ static void *wrapped_GDK_zalloc_nojump(s
                }                                                               
       \
                b = COLnew(0, TYPE_##tpename, count, TRANSIENT);                
       \
                if (!b) {                                                       
       \
-                       longjmp(jump_buffer[THRgettid()], 2);                   
           \
+                       if (option_enable_longjmp) 
longjmp(jump_buffer[THRgettid()], 2);   \
+                       else return;                                            
           \
                }                                                               
       \
                self->bat = (void*) b;                                          
       \
                self->count = count;                                            
       \
@@ -444,12 +453,14 @@ static str CUDFeval(Client cntxt, MalBlk
        // the input data
 
        // we remove them from the pthread_sigmask
-       (void)sigemptyset(&signal_set);
-       (void)sigaddset(&signal_set, SIGSEGV);
-       (void)sigaddset(&signal_set, SIGBUS);
-       (void)pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
+       if (option_enable_mprotect) {
+               (void)sigemptyset(&signal_set);
+               (void)sigaddset(&signal_set, SIGSEGV);
+               (void)sigaddset(&signal_set, SIGBUS);
+               (void)pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL);
 
-       memset(&sa, 0, sizeof(sa));
+               memset(&sa, 0, sizeof(sa));
+       }
 
        if (!grouped) {
                sql_subfunc *sqlmorefun =
@@ -1216,75 +1227,79 @@ static str CUDFeval(Client cntxt, MalBlk
        // set up a longjmp point
        // this longjmp point is used for some error handling in the C function
        // such as failed mallocs
-       ret = setjmp(jump_buffer[tid]);
-       if (ret < 0) {
-               // error value
-               msg = createException(MAL, "cudf.eval", "Failed setjmp: %s",
-                                                         strerror(errno));
-               errno = 0;
-               goto wrapup;
-       } else if (ret > 0) {
-               if (ret == 1) {
-                       msg = createException(MAL, "cudf.eval", "Attempting to 
write to "
-                                                                               
                        "the input or triggered a "
-                                                                               
                        "segfault/bus error");
-               } else if (ret == 2) {
-                       msg = createException(MAL, "cudf.eval",
-                                                                 "Malloc 
failure in internal function!");
-               } else {
-                       // we jumped here
-                       msg = createException(MAL, "cudf.eval", "We longjumped 
here "
-                                                                               
                        "because of an error, but "
-                                                                               
                        "we don't know which!");
+       if (option_enable_longjmp) {
+               ret = setjmp(jump_buffer[tid]);
+               if (ret < 0) {
+                       // error value
+                       msg = createException(MAL, "cudf.eval", "Failed setjmp: 
%s",
+                                                                 
strerror(errno));
+                       errno = 0;
+                       goto wrapup;
+               } else if (ret > 0) {
+                       if (ret == 1) {
+                               msg = createException(MAL, "cudf.eval", 
"Attempting to write to "
+                                                                               
                                "the input or triggered a "
+                                                                               
                                "segfault/bus error");
+                       } else if (ret == 2) {
+                               msg = createException(MAL, "cudf.eval",
+                                                                         
"Malloc failure in internal function!");
+                       } else {
+                               // we jumped here
+                               msg = createException(MAL, "cudf.eval", "We 
longjumped here "
+                                                                               
                                "because of an error, but "
+                                                                               
                                "we don't know which!");
+                       }
+                       goto wrapup;
                }
-               goto wrapup;
        }
 
        // set up the signal handler for catching segfaults
-       memset(&sa, 0, sizeof(sa));
-       sa.sa_flags = SA_SIGINFO;
-       sigfillset(&sa.sa_mask);
-       sa.sa_sigaction = handler;
-       if (sigaction(SIGSEGV, &sa, &oldsa) == -1 ||
-               sigaction(SIGBUS, &sa, &oldsb) == -1) {
-               msg = createException(MAL, "cudf.eval",
-                                                         "Failed to set signal 
handler: %s",
-                                                         strerror(errno));
-               errno = 0;
-               goto wrapup;
-       }
-
-       // actually mprotect the regions now that the signal handlers are set
-       region_iter = regions;
-       while (region_iter) {
-               if (mprotect(region_iter->addr, region_iter->len, PROT_READ) < 
0) {
+       if (option_enable_mprotect) {
+               memset(&sa, 0, sizeof(sa));
+               sa.sa_flags = SA_SIGINFO;
+               sigfillset(&sa.sa_mask);
+               sa.sa_sigaction = handler;
+               if (sigaction(SIGSEGV, &sa, &oldsa) == -1 ||
+                       sigaction(SIGBUS, &sa, &oldsb) == -1) {
+                       msg = createException(MAL, "cudf.eval",
+                                                                 "Failed to 
set signal handler: %s",
+                                                                 
strerror(errno));
+                       errno = 0;
                        goto wrapup;
                }
-               region_iter = region_iter->next;
+               // actually mprotect the regions now that the signal handlers 
are set
+               region_iter = regions;
+               while (region_iter) {
+                       if (mprotect(region_iter->addr, region_iter->len, 
PROT_READ) < 0) {
+                               goto wrapup;
+                       }
+                       region_iter = region_iter->next;
+               }
        }
-
        // call the actual jitted function
        msg = func(inputs, outputs, wrapped_GDK_malloc);
 
-       // clear any mprotected regions
-       while (regions) {
-               mprotected_region *next = regions->next;
-               clear_mprotect(regions->addr, regions->len);
-               GDKfree(regions);
-               regions = next;
+
+       if (option_enable_mprotect) {
+               // clear any mprotected regions
+               while (regions) {
+                       mprotected_region *next = regions->next;
+                       clear_mprotect(regions->addr, regions->len);
+                       GDKfree(regions);
+                       regions = next;
+               }
+               // clear the signal handlers
+               if (sigaction(SIGSEGV, &oldsa, NULL) == -1 ||
+                       sigaction(SIGBUS, &oldsb, NULL) == -1) {
+                       msg = createException(MAL, "cudf.eval",
+                                                                 "Failed to 
unset signal handler: %s",
+                                                                 
strerror(errno));
+                       errno = 0;
+                       goto wrapup;
+               }
+               memset(&sa, 0, sizeof(sa));
        }
 
-       // clear the signal handlers
-       if (sigaction(SIGSEGV, &oldsa, NULL) == -1 ||
-               sigaction(SIGBUS, &oldsb, NULL) == -1) {
-               msg = createException(MAL, "cudf.eval",
-                                                         "Failed to unset 
signal handler: %s",
-                                                         strerror(errno));
-               errno = 0;
-               goto wrapup;
-       }
-       memset(&sa, 0, sizeof(sa));
-
        if (msg) {
                // failure in function
                msg = createException(MAL, "cudf.eval", "%s", msg);
@@ -1472,26 +1487,30 @@ static str CUDFeval(Client cntxt, MalBlk
 wrapup:
        // cleanup
        // remove the signal handler, if any was set
-       if (sa.sa_sigaction) {
-               sigaction(SIGSEGV, &oldsa, NULL);
-               sigaction(SIGBUS, &oldsb, NULL);
+       if (option_enable_mprotect) {
+               if (sa.sa_sigaction) {
+                       sigaction(SIGSEGV, &oldsa, NULL);
+                       sigaction(SIGBUS, &oldsb, NULL);
 
-               memset(&sa, 0, sizeof(sa));
-       }
-       // clear any mprotected regions
-       while (regions) {
-               mprotected_region *next = regions->next;
-               clear_mprotect(regions->addr, regions->len);
-               GDKfree(regions);
-               regions = next;
+                       memset(&sa, 0, sizeof(sa));
+               }
+               // clear any mprotected regions
+               while (regions) {
+                       mprotected_region *next = regions->next;
+                       clear_mprotect(regions->addr, regions->len);
+                       GDKfree(regions);
+                       regions = next;
+               }
        }
        while (allocated_regions[tid]) {
                allocated_region *next = allocated_regions[tid]->next;
                GDKfree(allocated_regions[tid]);
                allocated_regions[tid] = next;
        }
-       // block segfaults and bus errors again after we exit
-       (void)pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+       if (option_enable_mprotect) {
+               // block segfaults and bus errors again after we exit
+               (void)pthread_sigmask(SIG_BLOCK, &signal_set, NULL);
+       }
        // argument names (input)
        if (args) {
                for (i = 0; i < (size_t)pci->argc; i++) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to