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
}