| 729 | } |
| 730 | |
| 731 | void ensure_plugins_loaded() { |
| 732 | ensure_initialized(); |
| 733 | if (!can_acquire_gil()) { |
| 734 | LOG_WARN("Python GIL state not ready, skipping plugin load"); |
| 735 | return; |
| 736 | } |
| 737 | |
| 738 | std::vector<std::string> to_load; |
| 739 | { |
| 740 | const GilAcquire gil; |
| 741 | std::lock_guard lock(g_plugin_init_mutex); |
| 742 | if (!ensure_python_bridge_ready_locked()) { |
| 743 | LOG_WARN("Python bridge not ready, skipping plugin load"); |
| 744 | return; |
| 745 | } |
| 746 | if (are_plugins_loaded()) { |
| 747 | return; |
| 748 | } |
| 749 | to_load = discover_enabled_plugins_locked(); |
| 750 | LOG_INFO("Plugin autoload: {} plugin(s) enabled for startup", to_load.size()); |
| 751 | } |
| 752 | |
| 753 | for (const auto& name : to_load) { |
| 754 | const GilAcquire gil; |
| 755 | if (load_single_plugin_locked(name)) { |
| 756 | LOG_INFO("Loaded plugin: {}", name); |
| 757 | } else { |
| 758 | LOG_ERROR("Failed to load plugin: {}", name); |
| 759 | } |
| 760 | } |
| 761 | |
| 762 | mark_plugins_loaded(); |
| 763 | } |
| 764 | |
| 765 | void preload_user_plugins_async() { |
| 766 | if (!env_flag_enabled("LFS_PLUGIN_AUTOLOAD", true)) { |
no test coverage detected