Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using REDIRECT_MALLOC & GC_THREADS on macos by adding thread hooks to source #478

Closed
plajjan opened this issue Oct 12, 2022 · 15 comments
Closed

Comments

@plajjan
Copy link
Contributor

plajjan commented Oct 12, 2022

I'm trying to use libgc for the run time system of a programming language which compiles to C. Linux and Macos are the currently supported platforms. The run time system is written in C and parts of the stdlib is written in C which in turn uses certain C libraries, for example we use libuv for IO and yyjson for JSON encoding / decoding (which is exposed as a module in the language). The run time system is using multiple threads.

It might be possible to change all calls to malloc & friends in the source code. I attempted as much and have so far failed. libuv, yyjson and perhaps some other C libraries use malloc and it appears that all must be changed to use GC_malloc. Currently I'm running into segfaults which I believe is because I've missed to update to GC_malloc everywhere.

I'm currently attempting to use REDIRECT_MALLOC and it does appear to be working correctly on Linux (although I should do much more testing).

On MacOS I'm seeing the following:

 ./include/private/gcconfig.h:3282:5: error: REDIRECT_MALLOC with THREADS works at most on Linux
#   error REDIRECT_MALLOC with THREADS works at most on Linux

I reckon this is because the dlopen wrapper doesn't support injecting thread-something-hooks on macos, right?

I'd like to come up with a working solution for macos as well. REDIRECT_MALLOC, i.e. to catch malloc & friends at link time and redirect to GC_malloc seems like the best solution for me since it seamlessly works even for included C libraries (some of which I'm not sure supports custom malloc in code). I wonder, would it be possible to run like GC_INIT in my program to get the correct thread registration / hooks but to rely on REDIRECT_MALLOC for handling the actual malloc calls?

I attempted as much simply by including gc.h in the main program from where we start all threads and I run GC_INIT() very early on. I removed the error in gcconfig.h which prevents this setup and thus I'm able to compile my system. I've been able to run a few programs (written in Acton) like this. Is it reasonable to suspect this could actually work or is it simply foolish? Are there any other options for my scenario?

I've tried reading some source code and the docs/README.macros but can't make sense if this is a supported setup? Any feedback is highly appreciated!

@ivmai
Copy link
Owner

ivmai commented Oct 12, 2022

I suppose no one has tried it yet. Please comment out the #error and try. If it works on your side, then I am ready to remove the error line in master.

@ivmai
Copy link
Owner

ivmai commented Oct 14, 2022

Also, GC_INIT() call could be omitted, I think (provided you don't compile with THREAD_LOCAL_ALLOC defined.

@ivmai
Copy link
Owner

ivmai commented Oct 14, 2022

The most essential thing to make malloc redirection work correctly (in a multithreaded app) is to ensure pthread create and friends are always redirected to libgc ones. This works on Linux, I have not checked it on OS X.

@plajjan
Copy link
Contributor Author

plajjan commented Oct 15, 2022

Ah okay. So I'm currently doing GC_INIT as well and it all appears to be working fine on macos. Great success... I haven't merged use of the GC yet (into the language run time I'm talking about) because of intermittent failures (that could be unrelated to GC)... I'll get back once I've tracked that down...

@ivmai
Copy link
Owner

ivmai commented Oct 20, 2022

I've been able to run a few programs (written in Acton)

actonlang/acton#952
(Just to keep this linked.)

@plajjan
Copy link
Contributor Author

plajjan commented Nov 14, 2022

@ivmai so we're using libgc in Acton across both Linux and MacOS. We are redirecting malloc & friends at link time and including gc.h with GC_THREADS=1 in source to get thread hooking working. It seems to be working just fine!

I get the compilation working simple by removing the error message in gcconfig.h from the Makefile in bdwgc, see https://github.com/actonlang/acton/blob/main/Makefile#L372

I think it's good that we somehow guide the user of bdwgc that they have to do something to get thread hooking working and since we can't do the dlopen hook on mac, it has to be source, which we cannot easily detect from the bdwgc. Maybe add a variable YES_I_HAVE_HOOKED_THREAD_CREATION_IN_SOURCE to suppress the warning and make it explicit to the user? ;)

@plajjan
Copy link
Contributor Author

plajjan commented Nov 14, 2022

Also for the record, it took some time to merge this because I was facing intermittent failures. I had a hunch they were not related to the GC... and they were not. It was really unrelated, but the GC caused the bug to be triggered much more frequently, due to the use of signals.

@ivmai
Copy link
Owner

ivmai commented Nov 15, 2022

I get the compilation working simple by removing the error message in gcconfig.h from the Makefile in bdwgc, see https://github.com/actonlang/acton/blob/main/Makefile#L372

Okay, I'll remove the error directive. (Or relax the condition)

@ivmai
Copy link
Owner

ivmai commented Nov 15, 2022

I think it's good that we somehow guide the user of bdwgc that they have to do something to get thread hooking working and since we can't do the dlopen hook on mac, it has to be source, which we cannot easily detect from the bdwgc. Maybe add a variable YES_I_HAVE_HOOKED_THREAD_CREATION_IN_SOURCE to suppress the warning and make it explicit to the user? ;)

Not sure how to inform the client about this, probably add a warning to configure/cmake (like we have the one about GC_INIT).
Probably make the documentation better.
Adding a macro is not good I think, because libgc might come to client in a binary format already (e.g. built with --enable-malloc-redirection)

@ivmai
Copy link
Owner

ivmai commented Nov 15, 2022

Also for the record, it took some time to merge this because I was facing intermittent failures. I had a hunch they were not related to the GC... and they were not. It was really unrelated, but the GC caused the bug to be triggered much more frequently, due to the use of signals.

Sounds good;) There was a case when gctest helped to catch some bugs in signal processing in some OS kernel ;)

@ivmai
Copy link
Owner

ivmai commented Nov 15, 2022

so we're using libgc in Acton across both Linux and MacOS

Cool, congratulations! As you say it was not trivial and you had to do debugging.
I've mentioned Acton on bdwgc clients page.

@ivmai
Copy link
Owner

ivmai commented Nov 15, 2022

Okay, I'll remove the error directive. (Or relax the condition)

Keeping the issue open for now

@ivmai
Copy link
Owner

ivmai commented Nov 17, 2022

@plajjan GC_USE_DLOPEN_WRAP is not working on MacOS, right?

#   ifdef GC_USE_DLOPEN_WRAP
#     include <dlfcn.h>
...
      /* FIXME: Needs work for DARWIN and True64 (OSF1) */

ivmai pushed a commit that referenced this issue Nov 17, 2022
Issue #478 (bdwgc).

The malloc (and friends) redirection in a multi-threaded client may
work even on platforms other than Linux (as confirmed on MacOS)
provided the client ensures all the client threads are registered with
the collector, e.g. by using the preprocessor-based interception of
the thread primitives (i.e., define GC_THREADS and include gc.h from
all the client files those are using pthread_create and friends).

* include/private/gcconfig.h [!CPPCHECK && REDIRECT_MALLOC && THREADS
&& !LINUX && !REDIRECT_MALLOC_IN_HEADER]: Remove error preprocessor
directive; add comment.
@ivmai
Copy link
Owner

ivmai commented Nov 17, 2022

Keeping the issue open for now

Closing now

@ivmai ivmai closed this as completed Nov 17, 2022
@plajjan
Copy link
Contributor Author

plajjan commented Nov 17, 2022

@plajjan GC_USE_DLOPEN_WRAP is not working on MacOS, right?

#   ifdef GC_USE_DLOPEN_WRAP
#     include <dlfcn.h>
...
      /* FIXME: Needs work for DARWIN and True64 (OSF1) */

Hmm, so I'm not sure I have actually tried the dlopen wrap code on Mac. I think I only got as far as trying to compile it, when I got the REDIRECT_MALLOC with THREADS works at most on Linux error and figured whomever wrote dlopen knew it could never work on Mac and thus I gave up on it. Instead I started investigating other approaches, namely fixing thread setup by including gc.h... so I don't actually know if dlopen wraps works or not on mac.

For Acton, I think the source-include-gc approach is better anyway since we want to be able to do fully static linking, in which case we wouldn't be able to dlopen wrap the pthread dynamic linking anyway...

ivmai pushed a commit that referenced this issue Mar 14, 2023
Issue #478 (bdwgc).

The malloc (and friends) redirection in a multi-threaded client may
work even on platforms other than Linux (as confirmed on MacOS)
provided the client ensures all the client threads are registered with
the collector, e.g. by using the preprocessor-based interception of
the thread primitives (i.e., define GC_THREADS and include gc.h from
all the client files those are using pthread_create and friends).

* include/private/gcconfig.h [!CPPCHECK && REDIRECT_MALLOC && THREADS
&& !LINUX && !REDIRECT_MALLOC_IN_HEADER]: Remove error preprocessor
directive; add comment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants