Remove reliance on static initializers for registration #359

Open
opened 2024-05-29 12:50:49 +00:00 by delroth · 9 comments
Member

A few places in Lix rely on static initializers to register various ops or backends. This is generally a bad idea: static initializers have undefined execution ordering which can vary across builds or even sometimes across runs, they break inter-module dependency analysis which can lead to really weird behavior with static .a builds, they break a whole bunch of static analysis / unused code detection, etc.

They also happen to be global and impossible to be made not-global, which could impair plans for a better liblix.

Let's instead switch to explicit registration of those ops / backends / ... as part of an "init" function/method. This will keep them as global for now - this proposed change is neutral on that dimension. The old Register* structs used for static initializer registration will be kept in the short term as __attribute__((deprecated))for plugin compatibility, but this might be revisited if we decide not to care about plugin source compatibility.

Known places to update:

  • RegisterLegacyCommand (cl/1905)
  • RegisterCommand (cl/2812)
  • GlobalConfig::Register
  • RegisterStoreImplementation (cl/1385)
  • RegisterPrimOp
  • Fix plugin-files setting documentation (cl/2826)
A few places in Lix rely on static initializers to register various ops or backends. This is generally a bad idea: static initializers have undefined execution ordering which can vary across builds or even sometimes across runs, they break inter-module dependency analysis which can lead to really weird behavior with static .a builds, they break a whole bunch of static analysis / unused code detection, etc. They also happen to be global and impossible to be made not-global, which could impair plans for a better liblix. Let's instead switch to explicit registration of those ops / backends / ... as part of an "init" function/method. This will keep them as global for now - this proposed change is neutral on that dimension. The old `Register*` structs used for static initializer registration will be kept in the short term as `__attribute__((deprecated))`for plugin compatibility, but this might be revisited if we decide not to care about plugin source compatibility. Known places to update: - [x] RegisterLegacyCommand (cl/1905) - [x] RegisterCommand (cl/2812) - [ ] GlobalConfig::Register - [x] RegisterStoreImplementation (cl/1385) - [ ] RegisterPrimOp - [x] Fix `plugin-files` setting documentation (cl/2826)
Member

The beginning for RegisterPrimOp removal is at https://gerrit.lix.systems/c/lix/+/1342

The beginning for `RegisterPrimOp` removal is at https://gerrit.lix.systems/c/lix/+/1342
Author
Member

Of the cases I've listed, I think GlobalConfig::Register will likely be the thorniest. It's being used across shared libraries, which means it's really not trivial to invert the dependency without introducing loops. Most likely it will need a fairly major refactor of the initialization API for all the sub libs in Lix.

The other ones seem self contained to a single shared module so they should be easier.

Of the cases I've listed, I think `GlobalConfig::Register` will likely be the thorniest. It's being used across shared libraries, which means it's really not trivial to invert the dependency without introducing loops. Most likely it will need a fairly major refactor of the initialization API for all the sub libs in Lix. The other ones seem self contained to a single shared module so they should be easier.
Author
Member

cl/1385 should take care of RegisterStoreImplementation

cl/1385 should take care of `RegisterStoreImplementation`
Member

This issue was mentioned on Gerrit on the following CLs:

  • commit message in cl/1385 ("libstore: remove static initializers for Store registrations")
  • commit message in cl/1905 ("Remove static initializers for RegisterLegacyCommand")
  • commit message in cl/1904 ("liblegacy: init")
  • commit message in cl/2812 ("Remove static initializers for CommandRegistry")
  • commit message in cl/2826 ("plugins: support nix_plugin_entry, do some minor reworks")
<!-- GERRIT_LINKBOT: {"cls": [{"backlink": "https://gerrit.lix.systems/c/lix/+/1385", "number": 1385, "kind": "commit message"}, {"backlink": "https://gerrit.lix.systems/c/lix/+/1905", "number": 1905, "kind": "commit message"}, {"backlink": "https://gerrit.lix.systems/c/lix/+/1904", "number": 1904, "kind": "commit message"}, {"backlink": "https://gerrit.lix.systems/c/lix/+/2812", "number": 2812, "kind": "commit message"}, {"backlink": "https://gerrit.lix.systems/c/lix/+/2826", "number": 2826, "kind": "commit message"}], "cl_meta": {"1385": {"change_title": "libstore: remove static initializers for Store registrations"}, "1905": {"change_title": "Remove static initializers for `RegisterLegacyCommand`"}, "1904": {"change_title": "liblegacy: init"}, "2812": {"change_title": "Remove static initializers for `CommandRegistry`"}, "2826": {"change_title": "plugins: support nix_plugin_entry, do some minor reworks"}}} --> This issue was mentioned on Gerrit on the following CLs: * commit message in [cl/1385](https://gerrit.lix.systems/c/lix/+/1385) ("libstore: remove static initializers for Store registrations") * commit message in [cl/1905](https://gerrit.lix.systems/c/lix/+/1905) ("Remove static initializers for `RegisterLegacyCommand`") * commit message in [cl/1904](https://gerrit.lix.systems/c/lix/+/1904) ("liblegacy: init") * commit message in [cl/2812](https://gerrit.lix.systems/c/lix/+/2812) ("Remove static initializers for `CommandRegistry`") * commit message in [cl/2826](https://gerrit.lix.systems/c/lix/+/2826) ("plugins: support nix_plugin_entry, do some minor reworks")
Owner

Removed RegisterLegacyCommand in https://gerrit.lix.systems/c/lix/+/1905

Removed `RegisterLegacyCommand` in https://gerrit.lix.systems/c/lix/+/1905
Owner

Removed RegisterCommand in cl/2812

Removed `RegisterCommand` in cl/2812
Owner

Last couple should be pretty small

Last couple should be pretty small
Owner

Working on plugin-files.

edit: cl/2826

Working on plugin-files. edit: cl/2826
pennae added this to the 2.95 milestone 2025-12-01 14:51:44 +00:00
Owner

GlobalConfig::Register requires a large rearchitecture of the entire system due to how fucked our config handling is: main calls initNix calls initStore which loads the configuration file, so all config registrations must happen before initNix. since this is pretty much the first thing that happens at all we're well and truly fucked about this one.

RegisterPrimOp is not nearly as bad, but it requires plugins to expose an init_libexpr hook or something of the sort, which we currently do not have (but @raito needs for the flake extraction).

`GlobalConfig::Register` requires a large rearchitecture of the entire system due to how fucked our config handling is: main calls initNix calls initStore which loads the configuration file, so all config registrations must happen before `initNix`. since this is pretty much the first thing that happens *at all* we're well and truly fucked about this one. `RegisterPrimOp` is not nearly as bad, but it requires plugins to expose an `init_libexpr` hook or something of the sort, which we currently do not have (but @raito needs for the flake extraction).
Sign in to join this conversation.
No milestone
No project
No assignees
6 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lix-project/lix#359
No description provided.