comparison plugin/NativeVampPluginFactory.cpp @ 1776:5750b9e60818

Don't even ask to unload a library if we know about other plugins that are loaded from it. Plus debug tweaks
author Chris Cannam
date Mon, 09 Sep 2019 10:25:16 +0100
parents 70e172e6cc59
children 5f8fbbde08ff
comparison
equal deleted inserted replaced
1775:e3db163e3f50 1776:5750b9e60818
51 51
52 PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter() 52 PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
53 { 53 {
54 // see notes in vamp-sdk/hostext/PluginLoader.cpp from which this is drawn 54 // see notes in vamp-sdk/hostext/PluginLoader.cpp from which this is drawn
55 Vamp::Plugin *p = m_plugin; 55 Vamp::Plugin *p = m_plugin;
56
57 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
58 SVCERR << "PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter("
59 << this << " for plugin " << p << ")" << endl;
60 #endif
61
56 delete m_plugin; 62 delete m_plugin;
57 m_plugin = nullptr; 63 m_plugin = nullptr;
58 // acceptable use after free here, as pluginDeleted uses p only as 64 // acceptable use after free here, as pluginDeleted uses p only as
59 // pointer key and does not deref it 65 // pointer key and does not deref it
60 if (m_factory) m_factory->pluginDeleted(p); 66 if (m_factory) m_factory->pluginDeleted(p);
142 } 148 }
143 continue; 149 continue;
144 } 150 }
145 151
146 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 152 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
147 cerr << "NativeVampPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl; 153 SVCERR << "NativeVampPluginFactory::getPluginIdentifiers: Vamp descriptor found" << endl;
148 #endif 154 #endif
149 155
150 const VampPluginDescriptor *descriptor = nullptr; 156 const VampPluginDescriptor *descriptor = nullptr;
151 int index = 0; 157 int index = 0;
152 158
181 QString id = PluginIdentifier::createIdentifier 187 QString id = PluginIdentifier::createIdentifier
182 ("vamp", libpath, descriptor->identifier); 188 ("vamp", libpath, descriptor->identifier);
183 m_identifiers.push_back(id); 189 m_identifiers.push_back(id);
184 m_libraries[id] = libpath; 190 m_libraries[id] = libpath;
185 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 191 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
186 cerr << "NativeVampPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl; 192 SVCERR << "NativeVampPluginFactory::getPluginIdentifiers: Found plugin id " << id << " at index " << index << endl;
187 #endif 193 #endif
188 ++index; 194 ++index;
189 } 195 }
190 } 196 }
191 197
198 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
199 SVCERR << "NativeVampPluginFactory::getPluginIdentifiers: unloading library " << libraryHandle << endl;
200 #endif
201
192 if (DLCLOSE(libraryHandle) != 0) { 202 if (DLCLOSE(libraryHandle) != 0) {
193 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to unload library " << libpath << endl; 203 SVDEBUG << "WARNING: NativeVampPluginFactory::getPluginIdentifiers: Failed to unload library " << libpath << endl;
194 } 204 }
195 } 205 }
196 206
206 NativeVampPluginFactory::findPluginFile(QString soname, QString inDir) 216 NativeVampPluginFactory::findPluginFile(QString soname, QString inDir)
207 { 217 {
208 QString file = ""; 218 QString file = "";
209 219
210 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 220 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
211 cerr << "NativeVampPluginFactory::findPluginFile(\"" 221 SVCERR << "NativeVampPluginFactory::findPluginFile(\""
212 << soname << "\", \"" << inDir << "\")" 222 << soname << "\", \"" << inDir << "\")"
213 << endl; 223 << endl;
214 #endif 224 #endif
215 225
216 if (inDir != "") { 226 if (inDir != "") {
223 file = dir.filePath(QFileInfo(soname).fileName()); 233 file = dir.filePath(QFileInfo(soname).fileName());
224 234
225 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) { 235 if (QFileInfo(file).exists() && QFileInfo(file).isFile()) {
226 236
227 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 237 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
228 cerr << "NativeVampPluginFactory::findPluginFile: " 238 SVCERR << "NativeVampPluginFactory::findPluginFile: "
229 << "found trivially at " << file << endl; 239 << "found trivially at " << file << endl;
230 #endif 240 #endif
231 241
232 return file; 242 return file;
233 } 243 }
235 for (unsigned int j = 0; j < dir.count(); ++j) { 245 for (unsigned int j = 0; j < dir.count(); ++j) {
236 file = dir.filePath(dir[j]); 246 file = dir.filePath(dir[j]);
237 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) { 247 if (QFileInfo(file).baseName() == QFileInfo(soname).baseName()) {
238 248
239 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 249 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
240 cerr << "NativeVampPluginFactory::findPluginFile: " 250 SVCERR << "NativeVampPluginFactory::findPluginFile: "
241 << "found \"" << soname << "\" at " << file << endl; 251 << "found \"" << soname << "\" at " << file << endl;
242 #endif 252 #endif
243 253
244 return file; 254 return file;
245 } 255 }
246 } 256 }
247 257
248 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 258 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
249 cerr << "NativeVampPluginFactory::findPluginFile (with dir): " 259 SVCERR << "NativeVampPluginFactory::findPluginFile (with dir): "
250 << "not found" << endl; 260 << "not found" << endl;
251 #endif 261 #endif
252 262
253 return ""; 263 return "";
254 264
256 266
257 QFileInfo fi(soname); 267 QFileInfo fi(soname);
258 268
259 if (fi.isAbsolute() && fi.exists() && fi.isFile()) { 269 if (fi.isAbsolute() && fi.exists() && fi.isFile()) {
260 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 270 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
261 cerr << "NativeVampPluginFactory::findPluginFile: " 271 SVCERR << "NativeVampPluginFactory::findPluginFile: "
262 << "found trivially at " << soname << endl; 272 << "found trivially at " << soname << endl;
263 #endif 273 #endif
264 return soname; 274 return soname;
265 } 275 }
266 276
277 if (file != "") return file; 287 if (file != "") return file;
278 } 288 }
279 } 289 }
280 290
281 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 291 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
282 cerr << "NativeVampPluginFactory::findPluginFile: " 292 SVCERR << "NativeVampPluginFactory::findPluginFile: "
283 << "not found" << endl; 293 << "not found" << endl;
284 #endif 294 #endif
285 295
286 return ""; 296 return "";
287 } 297 }
301 311
302 QString type, soname, label; 312 QString type, soname, label;
303 PluginIdentifier::parseIdentifier(identifier, type, soname, label); 313 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
304 if (type != "vamp") { 314 if (type != "vamp") {
305 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 315 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
306 cerr << "NativeVampPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl; 316 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Wrong factory for plugin type " << type << endl;
307 #endif 317 #endif
308 return nullptr; 318 return nullptr;
309 } 319 }
310 320
311 QString found = findPluginFile(soname); 321 QString found = findPluginFile(soname);
314 SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl; 324 SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: Failed to find library file " << soname << endl;
315 return nullptr; 325 return nullptr;
316 } else if (found != soname) { 326 } else if (found != soname) {
317 327
318 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 328 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
319 cerr << "NativeVampPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl; 329 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Given library name was " << soname << ", found at " << found << endl;
320 cerr << soname << " -> " << found << endl; 330 SVCERR << soname << " -> " << found << endl;
321 #endif 331 #endif
322 332
323 } 333 }
324 334
325 soname = found; 335 soname = found;
354 if (plugin) { 364 if (plugin) {
355 m_handleMap[plugin] = libraryHandle; 365 m_handleMap[plugin] = libraryHandle;
356 rv = new PluginDeletionNotifyAdapter(plugin, this); 366 rv = new PluginDeletionNotifyAdapter(plugin, this);
357 } 367 }
358 368
359 // SVDEBUG << "NativeVampPluginFactory::instantiatePlugin: Constructed Vamp plugin, rv is " << rv << endl; 369 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
360 370 if (rv) {
361 //!!! need to dlclose() when plugins from a given library are unloaded 371 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
372 }
373 #endif
362 374
363 done: 375 done:
364 if (!rv) { 376 if (!rv) {
377 SVCERR << "NativeVampPluginFactory::instantiatePlugin: Failed to construct plugin" << endl;
365 if (DLCLOSE(libraryHandle) != 0) { 378 if (DLCLOSE(libraryHandle) != 0) {
366 SVDEBUG << "WARNING: NativeVampPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl; 379 SVDEBUG << "WARNING: NativeVampPluginFactory::instantiatePlugin: Failed to unload library " << soname << endl;
367 } 380 }
368 } 381 }
369
370 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
371 cerr << "NativeVampPluginFactory::instantiatePlugin: Instantiated plugin " << label << " from library " << soname << ": descriptor " << descriptor << ", rv "<< rv << ", label " << rv->getName() << ", outputs " << rv->getOutputDescriptors().size() << endl;
372 #endif
373 382
374 return rv; 383 return rv;
375 } 384 }
376 385
377 void 386 void
378 NativeVampPluginFactory::pluginDeleted(Vamp::Plugin *plugin) 387 NativeVampPluginFactory::pluginDeleted(Vamp::Plugin *plugin)
379 { 388 {
380 void *handle = m_handleMap[plugin]; 389 void *handle = m_handleMap[plugin];
381 if (handle) { 390 if (!handle) return;
382 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE 391
383 cerr << "unloading library " << handle << " for plugin " << plugin << endl;
384 #endif
385 DLCLOSE(handle);
386 }
387 m_handleMap.erase(plugin); 392 m_handleMap.erase(plugin);
393
394 #ifdef DEBUG_PLUGIN_SCAN_AND_INSTANTIATE
395 SVCERR << "NativeVampPluginFactory::pluginDeleted: Removed from handle map, which now has " << m_handleMap.size() << " entries" << endl;
396 #endif
397
398 for (auto h: m_handleMap) {
399 if (h.second == handle) {
400 // still in use
401 SVDEBUG << "NativeVampPluginFactory::pluginDeleted: Not unloading library " << handle << " as other plugins are still loaded from it" << endl;
402 return;
403 }
404 }
405
406 SVDEBUG << "NativeVampPluginFactory::pluginDeleted: Unloading library " << handle << " after last plugin from this library " << plugin << " was deleted" << endl;
407 DLCLOSE(handle);
388 } 408 }
389 409
390 QString 410 QString
391 NativeVampPluginFactory::getPluginCategory(QString identifier) 411 NativeVampPluginFactory::getPluginCategory(QString identifier)
392 { 412 {
425 QFile file(path[i] + "/" + dir[j]); 445 QFile file(path[i] + "/" + dir[j]);
426 446
427 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl; 447 // SVDEBUG << "LADSPAPluginFactory::generateFallbackCategories: about to open " << (path[i]+ "/" + dir[j]) << endl;
428 448
429 if (file.open(QIODevice::ReadOnly)) { 449 if (file.open(QIODevice::ReadOnly)) {
430 // cerr << "...opened" << endl;
431 QTextStream stream(&file); 450 QTextStream stream(&file);
432 QString line; 451 QString line;
433 452
434 while (!stream.atEnd()) { 453 while (!stream.atEnd()) {
435 line = stream.readLine(); 454 line = stream.readLine();
436 // cerr << "line is: \"" << line << "\"" << endl;
437 QString id = PluginIdentifier::canonicalise 455 QString id = PluginIdentifier::canonicalise
438 (line.section("::", 0, 0)); 456 (line.section("::", 0, 0));
439 QString cat = line.section("::", 1, 1); 457 QString cat = line.section("::", 1, 1);
440 m_taxonomy[id] = cat; 458 m_taxonomy[id] = cat;
441 // cerr << "NativeVampPluginFactory: set id \"" << id << "\" to cat \"" << cat << "\"" << endl;
442 } 459 }
443 } 460 }
444 } 461 }
445 } 462 }
446 } 463 }