Ok. I agree. On 2021/3/26 17:10, Michal Privoznik wrote: > There's no need to CC random developers - we are subscribed to the list. > > On 3/26/21 4:21 AM, wangjian wrote:> serialize access pci_get_strings function with a mutex.> > nodedev-init thread: >> nodeStateInitializeEnumerate -> >> udevEnumerateDevices-> >> udevProcessDeviceListEntry -> >> udevAddOneDevice -> >> udevGetDeviceDetails-> >> udevProcessPCI -> >> udevTranslatePCIIds -> >> pci_get_strings -> (libpciaccess) >> find_device_name -> >> populate_vendor -> >> d = realloc( vend->devices, (vend->num_devices + 1), * sizeof( struct pci_device_leaf ) ); >> vend->num_devices++; >> >> udev-event thread: >> udevEventHandleThread -> >> udevHandleOneDevice -> >> udevAddOneDevice-> >> udevGetDeviceDetails-> >> udevProcessPCI -> >> udevTranslatePCIIds -> >> pci_get_strings -> (libpciaccess) >> find_device_name -> >> populate_vendor -> >> d = realloc( vend->devices, (vend->num_devices + 1), * sizeof( struct pci_device_leaf ) ); >> vend->num_devices++; >> >> Since the functions provided by libpciaccess are not thread-safe, >> when the udev-event and nodedev-init threads of libvirt call >> the pci_get_strings function provided by libpaciaccess at the same time. >> It will appear that for the same address, realloc a large space first, >> and then realloc a small space, which triggers the 'invalid next size' of realloc, >> leading to the thread core. >> >> Signed-off-by: WangJian <wangjian161@xxxxxxxxxx> >> --- >> src/node_device/node_device_udev.c | 3 +++ >> 1 file changed, 3 insertions(+) >> >> diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c >> index 3f28858..cc752ba 100644 >> --- a/src/node_device/node_device_udev.c >> +++ b/src/node_device/node_device_udev.c >> @@ -331,6 +331,7 @@ udevGenerateDeviceName(struct udev_device *device, >> return 0; >> } >> >> +static pthread_mutex_t g_pciaccess_mutex = PTHREAD_MUTEX_INITIALIZER; > > We tend to use virMutex (even though it is pthread_mutex under the hood). > >> >> static int >> udevTranslatePCIIds(unsigned int vendor, >> @@ -350,11 +351,13 @@ udevTranslatePCIIds(unsigned int vendor, >> m.match_data = 0; >> >> /* pci_get_strings returns void */ >> + pthread_mutex_lock(&g_pciaccess_mutex); >> pci_get_strings(&m, >> &device_name, >> &vendor_name, >> NULL, >> NULL); >> + pthread_mutex_unlock(&g_pciaccess_mutex); >> >> *vendor_string = g_strdup(vendor_name); >> *product_string = g_strdup(device_name); >> > > Apart from that, the patch is correct. I'd squash this in and push if you agree: > > diff --git i/src/node_device/node_device_udev.c w/src/node_device/node_device_udev.c > index cc752bad32..3daa5c90ad 100644 > --- i/src/node_device/node_device_udev.c > +++ w/src/node_device/node_device_udev.c > @@ -331,7 +331,7 @@ udevGenerateDeviceName(struct udev_device *device, > return 0; > } > > -static pthread_mutex_t g_pciaccess_mutex = PTHREAD_MUTEX_INITIALIZER; > +static virMutex pciaccessMutex = VIR_MUTEX_INITIALIZER; > > static int > udevTranslatePCIIds(unsigned int vendor, > @@ -350,14 +350,14 @@ udevTranslatePCIIds(unsigned int vendor, > m.device_class_mask = 0; > m.match_data = 0; > > - /* pci_get_strings returns void */ > - pthread_mutex_lock(&g_pciaccess_mutex); > + /* pci_get_strings returns void and unfortunately is not thread safe. */ > + virMutexLock(&pciaccessMutex); > pci_get_strings(&m, > &device_name, > &vendor_name, > NULL, > NULL); > - pthread_mutex_unlock(&g_pciaccess_mutex); > + virMutexUnlock(&pciaccessMutex); > > *vendor_string = g_strdup(vendor_name); > *product_string = g_strdup(device_name); > > > Michal > > . >