@@ -617,6 +617,30 @@ static void netdata_get_sensors()
617617
618618static void netdata_sensors_monitor (void * ptr __maybe_unused )
619619{
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+
620644 heartbeat_t hb ;
621645 heartbeat_init (& hb , USEC_PER_SEC );
622646
@@ -628,6 +652,16 @@ static void netdata_sensors_monitor(void *ptr __maybe_unused)
628652
629653 netdata_get_sensors ();
630654 }
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 ();
631665}
632666
633667void 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,
644678
645679static int initialize (int update_every )
646680{
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.
665684
666685 sensors = dictionary_create_advanced (
667686 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)
842861
843862void do_Sensors_cleanup ()
844863{
864+ // Wait for sensor thread to finish
865+ // The thread handles its own COM cleanup (CoUninitialize) and pSensorManager release
845866 if (nd_thread_join (sensors_thread_update ))
846867 nd_log_daemon (NDLP_ERR , "Failed to join sensors thread update" );
847868
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
853871}
0 commit comments