Mercurial > hg > orthanc
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); |