- 
                Notifications
    
You must be signed in to change notification settings  - Fork 557
 
Open
Description
Hi,
I am currently using Codon-compiled shared library (.so) in a single-threaded context, LSAN (Leak Sanitizer) reports memory leaks originating from libomp.so, despite explicitly setting GC_set_markers_count to 1 before loading the shared library.
I wanna use Codon-compiled so's with dlopen/dlsym, seems I have to call main in the so to get something initialized, but it seems to be a mistake. Calling main introduced the leak.
Codon Version: v0.18.2
Reduced reproduce sample:
Host
#include <iostream>
#include <fstream>
#include <memory>
#include <sstream>
#include <vector>
#include <dlfcn.h>
#include <unistd.h>
#ifndef LD_BIN
#define LD_BIN "ld.lld-19"
#endif
#ifndef CODON_PATH
#define CODON_PATH "/home/metaloxide/doc/codon"
#endif
#define CODON_BIN            CODON_PATH "/bin/codon"
#define CODON_LIB_PATH       CODON_PATH "/lib"
#define CODON_LIB_INNER_PATH CODON_LIB_PATH "/codon"
#define CODON_RUNTIME_PATH   CODON_LIB_INNER_PATH "/libcodonrt.so"
std::pair<std::string, int> exec(char const* cmd) {
  // 1 GB
  std::unique_ptr<char[]> buffer =
    std::make_unique<char[]>(1 * 1024 * 1024 * 1024);
  std::string result;
  std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd, "r"), &pclose);
  if (!pipe) {
    throw std::runtime_error("popen() failed");
  }
  while (fgets(buffer.get(), 1 * 1024 * 1024 * 1024, pipe.get()) != nullptr) {
    result += buffer.get();
  }
  // The pclose will be automatically called when pipe goes out of scope
  int status = WEXITSTATUS(pipe.get() ? pclose(pipe.release()) : -1);
  return {result, status};
}
struct BoehmGCHandlers {
  std::unique_ptr<void, std::integral_constant<decltype(&dlclose), &dlclose>>
    rt;
  void (*GC_set_markers_count)(unsigned) = {};
  void (*GC_gcollect_and_unmap)() = {};
  void (*GC_clear_roots)() = {};
  void (*GC_deinit)() = {};
  size_t (*GC_get_memory_use)() = {};
};
static BoehmGCHandlers* bdwgc_handlers = nullptr;
BoehmGCHandlers config_boehm_gc() {
  std::cout << CODON_RUNTIME_PATH << std::endl;
  void* codonrt = dlopen(CODON_RUNTIME_PATH, RTLD_LAZY);
  if (!codonrt) {
    throw std::runtime_error("dlopen() failed");
  }
  void (*GC_set_markers_count)(unsigned) =
    (void (*)(unsigned)) dlsym(codonrt, "GC_set_markers_count");
  GC_set_markers_count(1);
  BoehmGCHandlers handlers;
  handlers.rt.reset(codonrt);
  handlers.GC_set_markers_count = GC_set_markers_count;
  handlers.GC_gcollect_and_unmap =
    (void (*)()) dlsym(codonrt, "GC_gcollect_and_unmap");
  handlers.GC_clear_roots = (void (*)()) dlsym(codonrt, "GC_clear_roots");
  handlers.GC_deinit = (void (*)()) dlsym(codonrt, "GC_deinit");
  handlers.GC_get_memory_use =
    (size_t (*)()) dlsym(codonrt, "GC_get_memory_use");
  return handlers;
}
int main() {
  BoehmGCHandlers codonrt = config_boehm_gc();
  bdwgc_handlers = &codonrt;
  std::string compile_cmd;
  std::string name = "sized_rang_tagged_pointer_8_32";
  std::string link_cmd;
  {
    std::ostringstream cmdos;
    std::unique_ptr<char, std::integral_constant<decltype(&free), &free>>
      cwd_buf {getcwd(nullptr, 0)};
    char* cwd = cwd_buf.get();
    cmdos << CODON_BIN << " ";
    cmdos << "build --relocation-model=pic ";
    cmdos << "-o ";
    cmdos << cwd << "/" << name << ".codon.o ";
    cmdos << cwd << "/" << name << ".codon.py";
    std::string cmd1 = cmdos.str();
    cmdos = std::ostringstream{};
    cmdos << LD_BIN << " ";
    cmdos << cwd << "/" << name << ".codon.o ";
    cmdos << "-shared ";
    cmdos << "-L" << CODON_LIB_PATH << " ";
    cmdos << "-rpath " << CODON_LIB_PATH << " ";
    cmdos << "-L" << CODON_LIB_INNER_PATH << " ";
    cmdos << "-rpath " << CODON_LIB_INNER_PATH << " ";
    cmdos << "-lcodonrt ";
    cmdos << "-o ";
    cmdos << cwd << "/" << name << ".codon.so";
    std::string cmd2 = cmdos.str();
    std::cout << "cmd1: " << cmd1 << std::endl;
    std::cout << "cmd2: " << cmd2 << std::endl;
    compile_cmd = std::move(cmd1);
    link_cmd = std::move(cmd2);
  }
  auto compile_pair = exec(compile_cmd.c_str());
  if (compile_pair.second != 0) {
    std::cerr << "compile failed: " << compile_pair.first << std::endl;
    exit(1);
  }
  std::cout << "compile output: " << compile_pair.first << std::endl;
  auto link_pair = exec(link_cmd.c_str());
  if (link_pair.second != 0) {
    std::cerr << "link failed: " << link_pair.first << std::endl;
    exit(1);
  }
  std::cout << "link output: " << link_pair.first << std::endl;
  std::unique_ptr<void, std::integral_constant<decltype(&dlclose), &dlclose>>
    dl_handler_u {dlopen(
      ("./" + name + ".codon.so").c_str(),
      RTLD_NOW | RTLD_LOCAL /*| RTLD_DEEPBIND*/
    )};
  void* dl_handler = dl_handler_u.get();
  if (dl_handler == nullptr) {
    std::cerr << "dlopen failed: " << dlerror() << std::endl;
    exit(1);
  }
  std::cout << "dlopen output: " << dl_handler << std::endl;
  void (*test_main)(int, char**) =
    (void (*)(int, char**)) dlsym(dl_handler, "main");
  if (test_main == nullptr) {
    std::cerr << "dlsym failed: " << dlerror() << std::endl;
    exit(1);
  }
  std::cout << "dlsym output (main): " << (void*) (test_main) << std::endl;
  std::vector<char> mock_argv = {'t', 'e', 's', 't', '\0'};
  char* mock_argvp[1] = {mock_argv.data()};
  // Called main manually, please note here
  test_main(1, mock_argvp);
  bdwgc_handlers->GC_clear_roots();
  bdwgc_handlers->GC_gcollect_and_unmap();
}# sized_rang_tagged_pointer_8_32.py (Actually could be anything)
@export
def do_test_0(dump: Ptr[i8]) -> int:
  print("111")
  return 0
@export
def do_test_1(dump: Ptr[i8]) -> int:
  print("222")
  return 0
@export
def do_test_2(dump: Ptr[i8]) -> int:
  print("333")
  return 0After
clang++-19 /home/metaloxide/doc/temp/reduced.cpp -std=c++14 -fsanitize=address -o reduced && ./reducedI got
=================================================================
==964927==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 2237 byte(s) in 2 object(s) allocated from:
    #0 0x55c9d5877d6f in malloc (/cloudide/workspace/temp/reduced+0xcfd6f) (BuildId: 86fee8bc2cfa74ffb5de092eda4d1ce9b53ddc41)
    #1 0x7fa25bd56767  (<unknown module>)
Direct leak of 48 byte(s) in 1 object(s) allocated from:
    #0 0x55c9d5877f39 in calloc (/cloudide/workspace/temp/reduced+0xcff39) (BuildId: 86fee8bc2cfa74ffb5de092eda4d1ce9b53ddc41)
    #1 0x7fa25bd6b49a  (<unknown module>)
Direct leak of 24 byte(s) in 1 object(s) allocated from:
    #0 0x55c9d5877d6f in malloc (/cloudide/workspace/temp/reduced+0xcfd6f) (BuildId: 86fee8bc2cfa74ffb5de092eda4d1ce9b53ddc41)
    #1 0x7fa25bdeb627  (<unknown module>)
Indirect leak of 65 byte(s) in 1 object(s) allocated from:
    #0 0x55c9d5877d6f in malloc (/cloudide/workspace/temp/reduced+0xcfd6f) (BuildId: 86fee8bc2cfa74ffb5de092eda4d1ce9b53ddc41)
    #1 0x7fa25bdeb5b2  (<unknown module>)
where the unknown modules seem to be in libomp.so, is there any workround to get rid of it?
Thanks a lot
Metadata
Metadata
Assignees
Labels
No labels