Skip to content
This repository

fix: remove a handle without fail other handles greater than the removed one #2016

Closed
wants to merge 1 commit into from

1 participant

ulion
ulion
Collaborator

currently, remove a handle will fail all other handles which greater than the removed one, this will happen when more than one plugindirectory script running within a overlapped time.
it's a obvious bug since the handle supposed not always be 0, there is possibility following example happens:

ui make a plugin dir listing request, which assigned handle 0:
plugin with handle 0 begin
json-rpc make another plugin dir listing request, which assigned handle 1:
plugin with handle 1 begin
plugin with handle 0 end, in the current code, the handle will be erased
plugin with handle 1 call function like setEndOfDirectory but handle 1 does not existed, the globalHandles vector size is 1 now the CPluginDirectory object with original handle 1 now on the handle 0 position, so the setEndOfDirectory call will failed, it's a mistake, this commit fix this problem.

ulion ulion closed this
ulion ulion deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jan 02, 2013
ulion ulion fix: remove a handle without fail other handles greater than the remo…
…ved one.
d3a5f8b
This page is out of date. Refresh to see the latest.
43 xbmc/filesystem/PluginDirectory.cpp
@@ -73,7 +73,23 @@ void CPluginDirectory::removeHandle(int handle)
73 73 {
74 74 CSingleLock lock(m_handleLock);
75 75 if (handle >= 0 && handle < (int)globalHandles.size())
76   - globalHandles.erase(globalHandles.begin() + handle);
  76 + {
  77 + globalHandles[handle] = NULL;
  78 + while (handle >= 0 and handle + 1 == (int)globalHandles.size() && NULL == globalHandles[handle])
  79 + {
  80 + globalHandles.erase(globalHandles.begin() + handle);
  81 + --handle;
  82 + }
  83 + }
  84 +}
  85 +
  86 +// easy method to get dir object from handle.
  87 +// lock only in the function maybe not strong enough, make sure lock before call it.
  88 +CPluginDirectory *CPluginDirectory::dirFromHandle(int handle)
  89 +{
  90 + if (handle >= 0 && handle < (int)globalHandles.size())
  91 + return globalHandles[handle];
  92 + return NULL;
77 93 }
78 94
79 95 bool CPluginDirectory::StartScript(const CStdString& strPath, bool retrievingDir)
@@ -161,13 +177,13 @@ bool CPluginDirectory::GetPluginResult(const CStdString& strPath, CFileItem &res
161 177 bool CPluginDirectory::AddItem(int handle, const CFileItem *item, int totalItems)
162 178 {
163 179 CSingleLock lock(m_handleLock);
164   - if (handle < 0 || handle >= (int)globalHandles.size())
  180 + CPluginDirectory *dir = dirFromHandle(handle);
  181 + if (NULL == dir)
165 182 {
166 183 CLog::Log(LOGERROR, " %s - called with an invalid handle.", __FUNCTION__);
167 184 return false;
168 185 }
169 186
170   - CPluginDirectory *dir = globalHandles[handle];
171 187 CFileItemPtr pItem(new CFileItem(*item));
172 188 dir->m_listItems->Add(pItem);
173 189 dir->m_totalItems = totalItems;
@@ -178,13 +194,13 @@ bool CPluginDirectory::AddItem(int handle, const CFileItem *item, int totalItems
178 194 bool CPluginDirectory::AddItems(int handle, const CFileItemList *items, int totalItems)
179 195 {
180 196 CSingleLock lock(m_handleLock);
181   - if (handle < 0 || handle >= (int)globalHandles.size())
  197 + CPluginDirectory *dir = dirFromHandle(handle);
  198 + if (NULL == dir)
182 199 {
183 200 CLog::Log(LOGERROR, " %s - called with an invalid handle.", __FUNCTION__);
184 201 return false;
185 202 }
186 203
187   - CPluginDirectory *dir = globalHandles[handle];
188 204 CFileItemList pItemList;
189 205 pItemList.Copy(*items);
190 206 dir->m_listItems->Append(pItemList);
@@ -196,12 +212,12 @@ bool CPluginDirectory::AddItems(int handle, const CFileItemList *items, int tota
196 212 void CPluginDirectory::EndOfDirectory(int handle, bool success, bool replaceListing, bool cacheToDisc)
197 213 {
198 214 CSingleLock lock(m_handleLock);
199   - if (handle < 0 || handle >= (int)globalHandles.size())
  215 + CPluginDirectory *dir = dirFromHandle(handle);
  216 + if (NULL == dir)
200 217 {
201 218 CLog::Log(LOGERROR, " %s - called with an invalid handle.", __FUNCTION__);
202 219 return;
203 220 }
204   - CPluginDirectory *dir = globalHandles[handle];
205 221
206 222 // set cache to disc
207 223 dir->m_listItems->SetCacheToDisc(cacheToDisc ? CFileItemList::CACHE_IF_SLOW : CFileItemList::CACHE_NEVER);
@@ -219,14 +235,13 @@ void CPluginDirectory::EndOfDirectory(int handle, bool success, bool replaceList
219 235 void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod, const CStdString &label2Mask)
220 236 {
221 237 CSingleLock lock(m_handleLock);
222   - if (handle < 0 || handle >= (int)globalHandles.size())
  238 + CPluginDirectory *dir = dirFromHandle(handle);
  239 + if (NULL == dir)
223 240 {
224 241 CLog::Log(LOGERROR, "%s - called with an invalid handle.", __FUNCTION__);
225 242 return;
226 243 }
227 244
228   - CPluginDirectory *dir = globalHandles[handle];
229   -
230 245 // TODO: Add all sort methods and fix which labels go on the right or left
231 246 switch(sortMethod)
232 247 {
@@ -556,12 +571,12 @@ bool CPluginDirectory::WaitOnScriptResult(const CStdString &scriptPath, int scri
556 571 void CPluginDirectory::SetResolvedUrl(int handle, bool success, const CFileItem *resultItem)
557 572 {
558 573 CSingleLock lock(m_handleLock);
559   - if (handle < 0 || handle >= (int)globalHandles.size())
  574 + CPluginDirectory *dir = dirFromHandle(handle);
  575 + if (NULL == dir)
560 576 {
561 577 CLog::Log(LOGERROR, " %s - called with an invalid handle.", __FUNCTION__);
562 578 return;
563 579 }
564   - CPluginDirectory* dir = globalHandles[handle];
565 580
566 581 dir->m_success = success;
567 582 *dir->m_fileResult = *resultItem;
@@ -613,13 +628,13 @@ void CPluginDirectory::SetContent(int handle, const CStdString &strContent)
613 628 void CPluginDirectory::SetProperty(int handle, const CStdString &strProperty, const CStdString &strValue)
614 629 {
615 630 CSingleLock lock(m_handleLock);
616   - if (handle < 0 || handle >= (int)globalHandles.size())
  631 + CPluginDirectory *dir = dirFromHandle(handle);
  632 + if (NULL == dir)
617 633 {
618 634 CLog::Log(LOGERROR, "%s called with an invalid handle.", __FUNCTION__);
619 635 return;
620 636 }
621 637
622   - CPluginDirectory *dir = globalHandles[handle];
623 638 if (strProperty == "fanart_image")
624 639 dir->m_listItems->SetArt("fanart", strValue);
625 640 else
1  xbmc/filesystem/PluginDirectory.h
@@ -71,6 +71,7 @@ class CPluginDirectory : public IDirectory
71 71 static std::vector<CPluginDirectory*> globalHandles;
72 72 static int getNewHandle(CPluginDirectory *cp);
73 73 static void removeHandle(int handle);
  74 + static CPluginDirectory *dirFromHandle(int handle);
74 75 static CCriticalSection m_handleLock;
75 76
76 77 CFileItemList* m_listItems;

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.