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

Add a COB_LOAD_GLOBAL config option to modify dlopen behavior #209

Open
wants to merge 18 commits into
base: gcos4gnucobol-3.x
Choose a base branch
from

Conversation

florianschmidt1994
Copy link

@florianschmidt1994 florianschmidt1994 commented Jan 8, 2025

This PR adds a config option called COB_LOAD_GLOBAL which allows the flags of dlopen used in call.c to be changed between RTLD_GLOBAL and RTLD_LOCAL (see https://linux.die.net/man/3/dlopen)

Motivation

This flag is motivated by an ambition to be able to write a multi-threaded c program, that then loads libcob with dlmopen in one namespace per thread, effectively allowing us to call the same libcob / Cobol module from multiple threads in a "thread-safe" way. The image below shows the a very simplified intended call sequence

CanvasAsImage

Because there is a "bug" in dlopen that stops us from calling dlopen("module", RTLD_GLOBAL), this PR introduces an option to be able to change this flag to RTLD_LOCAL at runtime.

As at glibc 2.24, specifying the RTLD_GLOBAL flag when calling dlmopen() generates an error. Furthermore, specifying RTLD_GLOBAL when calling dlopen() results in a program crash (SIGSEGV) if the call is made from any object loaded in a namespace other than the initial namespace.

Docs

# Environment name:  COB_LOAD_GLOBAL
#   Parameter name:  load_global
#          Purpose:  tell the system loader to provide symbols in CALLed
#                    programs globally, allowing symbols to be found for linked
#                    libraries later
#             Type:  boolean
#             Note:  COBOL CALLs will always find symbols in already CALLed or
#                    pre-modules; this setting is mostly an advise to the system,
#                    not all systems are capable of loading libraries global/local
#          Default:  false
#          Example:  load_global true

Implementation

  • Change lt_dlopen from a macro definition to an actual function, which internally calls dlopen with the flags based on the configuration
  • Add cob_load_global / COB_LOAD_GLOBAL as a configuration
  • Add documentation to runtime.cfg about COB_LOAD_GLOBAL

@GitMensch
Copy link
Collaborator

Apart from the other PR's review to that branch, the change here makes the current scenario even more confusing.
I'd like to fix this in this PR (or up-front upstream).

After the changes:

  • instead of calling lt_dlopen we call a new static function cob_dlopen
  • this has the current code of this PR in for the case of dlopen usage
  • for the WIN32 variant it uses what is currently used there
  • for the libtool variant it uses lt_dlopenadvise() with an advise matching the runtime setting

@florianschmidt1994 can you please inspect the libtool variant (to test this you can simply undefine USE_LIBDL in config.h)?
I think I'll work on the cob_dlopen stuff late-evening.

@florianschmidt1994
Copy link
Author

florianschmidt1994 commented Jan 8, 2025

Yup, I'll check it out. Basically something like this, right?

static void* cob_dlopen(const char* filename) {
	#ifdef _WIN32
	if (x == NULL) {
		return GetModuleHandle (NULL);
	}
	return LoadLibrary(x);	
	#elif	defined(USE_LIBDL)
	int flags = cobsetptr->cob_load_global 
		? RTLD_LAZY | RTLD_GLOBAL
		: RTLD_LAZY | RTLD_LOCAL;

	return dlopen(filename, flags);
	# else
	// TODO: initialise lt_dladvise
	lt_dlopenadvise(filename, /*advise here*/);
}

@florianschmidt1994
Copy link
Author

@GitMensch I've tried out your suggestion in the latest commit and temporarily defined lt_dlopen as cob_dlopen to try it out. I've also added some indentation to the macros, does that conform with your style or should I remove them again?

Copy link
Collaborator

@GitMensch GitMensch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice update, we may be able to push that soon

Note: we still need the testcase addition - does not need to be something that benefit from this as this is hard to make portable - just do a simple CALL and CANCEL. We should have an easy one for COB_LOAD_CASE

ChangeLog Outdated Show resolved Hide resolved
ChangeLog Outdated Show resolved Hide resolved
libcob/call.c Outdated Show resolved Hide resolved
libcob/coblocal.h Outdated Show resolved Hide resolved
libcob/call.c Outdated Show resolved Hide resolved
config/runtime.cfg Show resolved Hide resolved
libcob/call.c Outdated Show resolved Hide resolved
@florianschmidt1994 florianschmidt1994 force-pushed the feature/add-dlopen-config-flag branch from f6aa350 to ab26e16 Compare January 9, 2025 09:31
@florianschmidt1994
Copy link
Author

florianschmidt1994 commented Jan 13, 2025

When developing, I've noticed some test failures, where some of them might be related to our change. On the latest commit of this repositories "main branch" (gcos4gnucobol-3.x), there are some test failures when the build is configured with --without-dl. These failures persist also with our changes applied.

Commit Hash Loader COB_LOAD_GLOBAL Test Failures
731b81a --without-dl not applicable 47 49 50 784 failed
731b81a not applicable no test failure

In the first version of this PR (bd80e8c), there is an additional test failure (781) when using COB_LOAD_GLOBAL=false, i.e. the default, and preloading where symbols are overwritten in an unexpected manner.

Commit Hash Loader COB_LOAD_GLOBAL Test Failures
bd80e8c false 781 failed
bd80e8c true no test failure
bd80e8c --without-dl false 47 49 50 781 failed
bd80e8c --without-dl true 47 49 50 failed

In history up to the latest commit (62de625), there exists a fix (see 1f4d607), the same that is already applied in WIN32 environments, to fix this.

Commit Hash Loader COB_LOAD_GLOBAL Test Failures
62de625 false no test failure
62de625 true no test failure
62de625 --without-dl false 47 49 50 failed
62de625 --without-dl true 47 49 50 failed

@florianschmidt1994 florianschmidt1994 changed the title WIP: Add a COB_LOAD_GLOBAL config option to modify dlopen behavior Add a COB_LOAD_GLOBAL config option to modify dlopen behavior Jan 13, 2025
@florianschmidt1994 florianschmidt1994 marked this pull request as ready for review January 13, 2025 10:24
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

Successfully merging this pull request may close these issues.

2 participants