@cryptotaxi247 / netdata-1 / commits / a87d38e34

Adjust windows sensors initialization (#21374)

* Chaneg sensor initialization to handle COM setup in the sensor thread * Fix COM initialization handling in sensor thread

Stelios Fragkakis committed Dec 1, 2025 at 21:13 UTC a87d38e34bae0a4b0b7e4158eb1a6ff75e235827
1 file changed +41 -23
src/collectors/windows.plugin/GetSensors.c
+41 -23
@@ -617,6 +617,30 @@ static void netdata_get_sensors()
617
618 static void netdata_sensors_monitor(void *ptr __maybe_unused)
619 {
620 + // Initialize COM for this thread - sensor thread only needs COM for Sensor API, not WMI
621 + HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
622 + bool com_initialized = SUCCEEDED(hr);
623 +
624 + // RPC_E_CHANGED_MODE means COM was already initialized in a different mode (e.g., COINIT_APARTMENTTHREADED)
625 + // In this case, COM is available but we didn't increment the reference count
626 + if (FAILED(hr) && hr != RPC_E_CHANGED_MODE) {
627 + nd_log(NDLS_COLLECTORS, NDLP_ERR,
628 + "Sensor thread: cannot initialize COM interface (error 0x%lX)", (unsigned long)hr);
629 + return;
630 + }
631 +
632 + // Create sensor manager instance for this thread
633 + hr = CoCreateInstance(
634 + &CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, &IID_ISensorManager, (void **)&pSensorManager);
635 + if (FAILED(hr)) {
636 + nd_log(NDLS_COLLECTORS, NDLP_ERR,
637 + "Sensor thread: cannot create ISensorManager (error 0x%lX)", (unsigned long)hr);
638 + // Only uninitialize if we successfully initialized COM ourselves
639 + if (com_initialized)
640 + CoUninitialize();
641 + return;
642 + }
643 +
644 heartbeat_t hb;
645 heartbeat_init(&hb, USEC_PER_SEC);
646
@@ -628,6 +652,16 @@ static void netdata_sensors_monitor(void *ptr __maybe_unused)
652
653 netdata_get_sensors();
654 }
655 +
656 + // Thread cleanup - release sensor manager and uninitialize COM
657 + if (pSensorManager) {
658 + pSensorManager->lpVtbl->Release(pSensorManager);
659 + pSensorManager = NULL;
660 + }
661 +
662 + // Only uninitialize if we successfully initialized COM ourselves
663 + if (com_initialized)
664 + CoUninitialize();
665 }
666
667 void dict_sensor_insert(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused)
@@ -644,24 +678,9 @@ void dict_sensor_insert(const DICTIONARY_ITEM *item __maybe_unused, void *value,
678
679 static int initialize(int update_every)
680 {
647 - // This is an internal plugin, if we initialize these two times, collector will fail. To avoid this
648 - // we call InitializeWMI to verify COM interface was already initialized.
649 - HRESULT hr = InitializeWMI();
650 - if (hr != S_OK) {
651 - hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
652 - if (FAILED(hr)) {
653 - nd_log(NDLS_COLLECTORS, NDLP_ERR, "Collector cannot initialize COM interface.");
654 - return -1;
655 - }
656 - }
657 -
658 - hr = CoCreateInstance(
659 - &CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, &IID_ISensorManager, (void **)&pSensorManager);
660 - if (FAILED(hr)) {
661 - nd_log(NDLS_COLLECTORS, NDLP_ERR, "Collector cannot initialize sensor API.");
662 - CoUninitialize();
663 - return -1;
664 - }
681 + // Note: COM and Sensor API initialization is now done in the sensor thread
682 + // (netdata_sensors_monitor) because COM must be initialized per-thread.
683 + // The sensor thread owns the pSensorManager instance and handles its cleanup.
684
685 sensors = dictionary_create_advanced(
686 DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL, sizeof(struct sensor_data));
@@ -842,12 +861,11 @@ int do_GetSensors(int update_every, usec_t dt __maybe_unused)
861
862 void do_Sensors_cleanup()
863 {
864 + // Wait for sensor thread to finish
865 + // The thread handles its own COM cleanup (CoUninitialize) and pSensorManager release
866 if (nd_thread_join(sensors_thread_update))
867 nd_log_daemon(NDLP_ERR, "Failed to join sensors thread update");
868
848 - if (pSensorManager) {
849 - pSensorManager->lpVtbl->Release(pSensorManager);
850 -
851 - CoUninitialize();
852 - }
869 + // Note: pSensorManager is owned and cleaned up by the sensor thread itself
870 + // No additional cleanup needed here since the thread has already released resources
871 }