What happens when exiting Julia after ccall is made?

I got into a strange situation where Julia would segfault when I exit from the REPL. It happens whenever I make any ccall to a C library function. This is a vendor package and I think it has some licensing-related code but why does it happen only at the time of exit?

So my question is: what does Julia do when it exits? Maybe it’s trying to unload the shared lib?

julia>

signal (11): Segmentation fault
while loading no file, in expression starting on line 0
_ZNSt8_Rb_treeISsSt4pairIKSsN5boost10shared_ptrI11rlm_licenseEEESt10_Select1stIS6_ESt4lessISsESaIS6_EE8_M_eraseEPSt13_Rb_tree_nodeIS6_E at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_ZNSt8_Rb_treeISsSt4pairIKSsN5boost10shared_ptrI11rlm_licenseEEESt10_Select1stIS6_ESt4lessISsESaIS6_EE8_M_eraseEPSt13_Rb_tree_nodeIS6_E at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_ZNSt8_Rb_treeISsSt4pairIKSsN5boost10shared_ptrI11rlm_licenseEEESt10_Select1stIS6_ESt4lessISsESaIS6_EE8_M_eraseEPSt13_Rb_tree_nodeIS6_E at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_Z23fc_release_all_licensesv at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_Z32fc_rlm_terminate_reprise_libraryv at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
unknown function (ip: 0x7f9d30f3fd0d)
pthread_once at /lib64/libpthread.so.0 (unknown line)
unknown function (ip: 0x7f9d314bba21)
unknown function (ip: 0x7f9d3029a75e)
unknown function (ip: 0x7f9d318ce480)
unknown function (ip: 0x7f9d813bfa68)
unknown function (ip: 0x7f9d8269595f)
Allocations: 1813374 (Pool: 1812168; Big: 1206); GC: 1
Segmentation fault

My version info:

Julia Version 0.6.2
Commit d386e40c17 (2017-12-13 18:08 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, broadwell)

The C standard library has an exit hook that shared libraries can register themselves for. Julia doesn’t do anything special here.

Got a new MWE - just calling dlopen will trigger this exit-segfault behavior.

julia> Libdl.dlopen("/opt/fincad/lib/libfincad_suite_64_2017.so")
Ptr{Void} @0x0000000002e01cf0

julia>

signal (11): Segmentation fault
while loading no file, in expression starting on line 0
_ZNSt8_Rb_treeISsSt4pairIKSsN5boost10shared_ptrI11rlm_licenseEEESt10_Select1stIS6_ESt4lessISsESaIS6_EE8_M_eraseEPSt13_Rb_tree_nodeIS6_E at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_ZNSt8_Rb_treeISsSt4pairIKSsN5boost10shared_ptrI11rlm_licenseEEESt10_Select1stIS6_ESt4lessISsESaIS6_EE8_M_eraseEPSt13_Rb_tree_nodeIS6_E at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_ZNSt8_Rb_treeISsSt4pairIKSsN5boost10shared_ptrI11rlm_licenseEEESt10_Select1stIS6_ESt4lessISsESaIS6_EE8_M_eraseEPSt13_Rb_tree_nodeIS6_E at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_Z23fc_release_all_licensesv at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
_Z32fc_rlm_terminate_reprise_libraryv at /opt/fincad/lib/libfincad_suite_64_2017.so (unknown line)
unknown function (ip: 0x7fecee03dd0d)
pthread_once at /lib64/libpthread.so.0 (unknown line)
unknown function (ip: 0x7fecee5b9a21)
unknown function (ip: 0x7feced39875e)
unknown function (ip: 0x7fecee9cc480)
unknown function (ip: 0x7fed4052fa68)
unknown function (ip: 0x7fed4180595f)
Allocations: 974017 (Pool: 972913; Big: 1104); GC: 0
Segmentation fault

Looks like Libdl.dlopen ends up calling dlopen:

https://github.com/JuliaLang/julia/blob/release-0.6/src/dlload.c#L145

I could create a simple C program that does the same but that won’t crash on exit. Maybe it’s time for me to compile Julia from source to track it down :sweat_smile:

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv)
{
    void *handle;
    char *error;

    handle = dlopen("libfincad_suite_64_2017.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }

    printf("good\n");
}

One suggestion is to try running your C program vs julia caller with LD_DEBUG and compare which shared libraries are pulled in.

It turns out that there’s a housekeeping function that I should call before exiting the application and that fixes the seg fault issue. Although I still don’t understand the difference between the Julia and C versions, I don’t have an immediate problem anymore. Thanks for the ideas!