comparison Plugins/Engine/OrthancPlugins.cpp @ 1768:70f544f9c38f

fix possible deadlock in custom database plugins
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 09 Nov 2015 17:39:42 +0100
parents 51db4a25a741
children 8790488ae98b
comparison
equal deleted inserted replaced
1767:b268756c2cb9 1768:70f544f9c38f
1285 _OrthancPluginService service, 1285 _OrthancPluginService service,
1286 const void* parameters) 1286 const void* parameters)
1287 { 1287 {
1288 VLOG(1) << "Calling service " << service << " from plugin " << plugin.GetPath(); 1288 VLOG(1) << "Calling service " << service << " from plugin " << plugin.GetPath();
1289 1289
1290 boost::recursive_mutex::scoped_lock lock(pimpl_->invokeServiceMutex_); 1290 if (service == _OrthancPluginService_DatabaseAnswer)
1291 {
1292 // This case solves a deadlock at (*) reported by James Webster
1293 // on 2015-10-27 that was present in versions of Orthanc <=
1294 // 0.9.4 and related to database plugins implementing a custom
1295 // index. The problem was that locking the database is already
1296 // ensured by the "ServerIndex" class if the invoked service is
1297 // "DatabaseAnswer".
1298
1299 const _OrthancPluginDatabaseAnswer& p =
1300 *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(parameters);
1301
1302 if (pimpl_->database_.get() != NULL)
1303 {
1304 pimpl_->database_->AnswerReceived(p);
1305 return true;
1306 }
1307 else
1308 {
1309 LOG(ERROR) << "Cannot invoke this service without a custom database back-end";
1310 throw OrthancException(ErrorCode_BadRequest);
1311 }
1312 }
1313
1314
1315 std::auto_ptr<boost::recursive_mutex::scoped_lock> lock; // (*)
1291 1316
1292 switch (service) 1317 switch (service)
1293 { 1318 {
1294 case _OrthancPluginService_GetOrthancPath: 1319 case _OrthancPluginService_GetOrthancPath:
1295 { 1320 {
1557 1582
1558 return true; 1583 return true;
1559 } 1584 }
1560 1585
1561 case _OrthancPluginService_DatabaseAnswer: 1586 case _OrthancPluginService_DatabaseAnswer:
1562 { 1587 throw OrthancException(ErrorCode_InternalError); // Implemented before locking (*)
1563 const _OrthancPluginDatabaseAnswer& p =
1564 *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(parameters);
1565
1566 if (pimpl_->database_.get() != NULL)
1567 {
1568 pimpl_->database_->AnswerReceived(p);
1569 return true;
1570 }
1571 else
1572 {
1573 LOG(ERROR) << "Cannot invoke this service without a custom database back-end";
1574 throw OrthancException(ErrorCode_BadRequest);
1575 }
1576 }
1577 1588
1578 case _OrthancPluginService_GetExpectedDatabaseVersion: 1589 case _OrthancPluginService_GetExpectedDatabaseVersion:
1579 { 1590 {
1580 const _OrthancPluginReturnSingleValue& p = 1591 const _OrthancPluginReturnSingleValue& p =
1581 *reinterpret_cast<const _OrthancPluginReturnSingleValue*>(parameters); 1592 *reinterpret_cast<const _OrthancPluginReturnSingleValue*>(parameters);