Ticket #931 (closed bug: fixed)

Opened 5 years ago

Last modified 5 years ago

Segfault on Win32 when loading multiple op libraries

Reported by: jonathan Owned by:
Priority: blocker Milestone:
Component: core Version: 1.4.0
Severity: release Keywords:
Cc: Language:
Patch status: Platform: win32

Description (last modified by jonathan) (diff)

Hi,

On Win32 + MS VC++, the following segfaults:

.loadlib 'math_ops'
.loadlib 'obscure_ops'
.sub 'main' :main
    say "alive"
.end

If I remove one or the other of these libraries, or re-order them, the effect is exactly the same. The segfault happens on line 1173 of src/runcore/main.c and always when loading the second dynops library (whichever one comes first seems to load just fine, and it explodes on the second one).

This is a serious issue since, IIRC, we're meant to have a Parrot release tomorrow, and since the Random PMC has been replaced by dynops Rakudo now needs to load two dynoplibs - both its own (perl6_ops) and also math_ops now. The upshot is that Rakudo is currently unbuildable on my platform (segfaults during compiling perl6.pir from PIR to PBC).

I'm trying to work out what's going on, but would really appreciate additional input from anyone else who can reproduce this and help debug the segfault. It doesn't seem to matter which dynop libraries are picked, and the above example is all stuff shipped with Parrot rather than being Rakudo specific.

Thanks,

Jonathan

Change History

Changed 5 years ago by jonathan

  • description modified (diff)

Changed 5 years ago by jonathan

I think that we end up looking at memory that a realloc has freed. This patch works around the issue by commenting out a probably more optimal code path. We could choose to rip out said optimization or work out a fix.

Index: src/runcore/main.c
===================================================================
--- src/runcore/main.c	(revision 40598)
+++ src/runcore/main.c	(working copy)
@@ -1085,6 +1085,7 @@
 
 */
 
+PARROT_EXPORT
 void
 dynop_register(PARROT_INTERP, ARGIN(PMC *lib_pmc))
 {
@@ -1141,13 +1142,13 @@
 
     new_evc_func_table = (op_func_t *)mem_sys_realloc(interp->evc_func_table,
             sizeof (op_func_t) * n_tot);
-    if (core->flags & OP_FUNC_IS_ALLOCATED) {
+    /*if (core->flags & OP_FUNC_IS_ALLOCATED) {
         new_func_table = (op_func_t *)mem_sys_realloc(core->op_func_table,
                 sizeof (op_func_t) * n_tot);
         new_info_table = (op_info_t *)mem_sys_realloc(core->op_info_table,
                 sizeof (op_info_t) * n_tot);
     }
-    else {
+    else {*/
         /* allocate new op_func and info tables */
         new_func_table = mem_allocate_n_typed(n_tot, op_func_t);
         new_info_table = mem_allocate_n_typed(n_tot, op_info_t);
@@ -1157,7 +1158,7 @@
             new_func_table[i] = interp->op_func_table[i];
             new_info_table[i] = interp->op_info_table[i];
         }
-    }
+    /*}*/
 
     /* add new */
     for (i = n_old; i < n_tot; ++i) {

Changed 5 years ago by jonathan

bacek++ pointed out on IRC that the above probably leaks memory per op-lib loaded, mind...

Changed 5 years ago by jonathan

  • status changed from new to closed
  • resolution set to fixed

Fixed by:

r40606 | bacek++ | trunk/src/runcore/main.c: [cage] Don't reuse reallocated func_table by old pointer in dynop_register

Thanks!

Jonathan

Note: See TracTickets for help on using tickets.