diff options
author | diva | 2009-04-18 16:37:05 +0000 |
---|---|---|
committer | diva | 2009-04-18 16:37:05 +0000 |
commit | 8e08dd20dc9fe785874943c7986f82af60ed1879 (patch) | |
tree | e73717f3a5c416514acb6bd363aad9a206a66360 | |
parent | Addresses mantis #3485. (diff) | |
download | opensim-SC-8e08dd20dc9fe785874943c7986f82af60ed1879.zip opensim-SC-8e08dd20dc9fe785874943c7986f82af60ed1879.tar.gz opensim-SC-8e08dd20dc9fe785874943c7986f82af60ed1879.tar.bz2 opensim-SC-8e08dd20dc9fe785874943c7986f82af60ed1879.tar.xz |
Thank you dslake for diagnosing and fixing a race condition in OGS1SecureInventoryServer (mantis #3483). The provided patch was slightly modified to narrow the locking scope to smaller portions of the functions. Applied the same locking to HGInventoryService, which suffered from the same race condition.
-rw-r--r-- | OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs | 156 | ||||
-rw-r--r-- | OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs | 122 |
2 files changed, 146 insertions, 132 deletions
diff --git a/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs b/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs index 156137e..98f5f68 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs | |||
@@ -77,52 +77,54 @@ namespace OpenSim.Region.Communications.Hypergrid | |||
77 | } | 77 | } |
78 | 78 | ||
79 | // grid/hypergrid mode | 79 | // grid/hypergrid mode |
80 | if (!m_RequestingInventory.ContainsKey(userID)) | 80 | lock (m_RequestingInventory) |
81 | { | 81 | { |
82 | m_RequestingInventory.Add(userID, callback); | 82 | if (!m_RequestingInventory.ContainsKey(userID)) |
83 | |||
84 | string invServer = GetUserInventoryURI(userID); | ||
85 | m_log.InfoFormat( | ||
86 | "[HGrid INVENTORY SERVICE]: Requesting inventory from {0}/GetInventory/ for user {1} ({2})", | ||
87 | /*_inventoryServerUrl*/ invServer, userID, userID.Guid); | ||
88 | |||
89 | try | ||
90 | { | 83 | { |
91 | 84 | m_RequestingInventory.Add(userID, callback); | |
92 | //RestSessionObjectPosterResponse<Guid, InventoryCollection> requester | ||
93 | // = new RestSessionObjectPosterResponse<Guid, InventoryCollection>(); | ||
94 | //requester.ResponseCallback = InventoryResponse; | ||
95 | |||
96 | //requester.BeginPostObject(invServer + "/GetInventory/", userID.Guid, session_id.ToString(), userID.ToString()); | ||
97 | GetInventoryDelegate d = GetInventoryAsync; | ||
98 | d.BeginInvoke(invServer, userID, session_id, GetInventoryCompleted, d); | ||
99 | |||
100 | } | 85 | } |
101 | catch (WebException e) | 86 | else |
102 | { | 87 | { |
103 | if (StatsManager.SimExtraStats != null) | 88 | m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: RequestInventoryForUser() - could not find user profile for {0}", userID); |
104 | StatsManager.SimExtraStats.AddInventoryServiceRetrievalFailure(); | 89 | return; |
105 | |||
106 | m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: Request inventory operation failed, {0} {1}", | ||
107 | e.Source, e.Message); | ||
108 | |||
109 | // Well, let's synthesize one | ||
110 | InventoryCollection icol = new InventoryCollection(); | ||
111 | icol.UserID = userID; | ||
112 | icol.Items = new List<InventoryItemBase>(); | ||
113 | icol.Folders = new List<InventoryFolderBase>(); | ||
114 | InventoryFolderBase rootFolder = new InventoryFolderBase(); | ||
115 | rootFolder.ID = UUID.Random(); | ||
116 | rootFolder.Owner = userID; | ||
117 | icol.Folders.Add(rootFolder); | ||
118 | InventoryResponse(icol); | ||
119 | } | 90 | } |
120 | } | 91 | } |
121 | else | 92 | string invServer = GetUserInventoryURI(userID); |
93 | m_log.InfoFormat( | ||
94 | "[HGrid INVENTORY SERVICE]: Requesting inventory from {0}/GetInventory/ for user {1} ({2})", | ||
95 | /*_inventoryServerUrl*/ invServer, userID, userID.Guid); | ||
96 | |||
97 | try | ||
122 | { | 98 | { |
123 | m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: RequestInventoryForUser() - could not find user profile for {0}", userID); | 99 | |
100 | //RestSessionObjectPosterResponse<Guid, InventoryCollection> requester | ||
101 | // = new RestSessionObjectPosterResponse<Guid, InventoryCollection>(); | ||
102 | //requester.ResponseCallback = InventoryResponse; | ||
103 | |||
104 | //requester.BeginPostObject(invServer + "/GetInventory/", userID.Guid, session_id.ToString(), userID.ToString()); | ||
105 | GetInventoryDelegate d = GetInventoryAsync; | ||
106 | d.BeginInvoke(invServer, userID, session_id, GetInventoryCompleted, d); | ||
107 | |||
124 | } | 108 | } |
125 | 109 | catch (WebException e) | |
110 | { | ||
111 | if (StatsManager.SimExtraStats != null) | ||
112 | StatsManager.SimExtraStats.AddInventoryServiceRetrievalFailure(); | ||
113 | |||
114 | m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: Request inventory operation failed, {0} {1}", | ||
115 | e.Source, e.Message); | ||
116 | |||
117 | // Well, let's synthesize one | ||
118 | InventoryCollection icol = new InventoryCollection(); | ||
119 | icol.UserID = userID; | ||
120 | icol.Items = new List<InventoryItemBase>(); | ||
121 | icol.Folders = new List<InventoryFolderBase>(); | ||
122 | InventoryFolderBase rootFolder = new InventoryFolderBase(); | ||
123 | rootFolder.ID = UUID.Random(); | ||
124 | rootFolder.Owner = userID; | ||
125 | icol.Folders.Add(rootFolder); | ||
126 | InventoryResponse(icol); | ||
127 | } | ||
126 | } | 128 | } |
127 | 129 | ||
128 | private delegate InventoryCollection GetInventoryDelegate(string url, UUID userID, UUID sessionID); | 130 | private delegate InventoryCollection GetInventoryDelegate(string url, UUID userID, UUID sessionID); |
@@ -447,62 +449,66 @@ namespace OpenSim.Region.Communications.Hypergrid | |||
447 | private void InventoryResponse(InventoryCollection response) | 449 | private void InventoryResponse(InventoryCollection response) |
448 | { | 450 | { |
449 | UUID userID = response.UserID; | 451 | UUID userID = response.UserID; |
450 | if (m_RequestingInventory.ContainsKey(userID)) | 452 | InventoryReceiptCallback callback = null; |
453 | lock (m_RequestingInventory) | ||
451 | { | 454 | { |
452 | m_log.InfoFormat("[HGrid INVENTORY SERVICE]: " + | 455 | if (m_RequestingInventory.ContainsKey(userID)) |
453 | "Received inventory response for user {0} containing {1} folders and {2} items", | 456 | { |
454 | userID, response.Folders.Count, response.Items.Count); | 457 | m_log.InfoFormat("[HGrid INVENTORY SERVICE]: " + |
458 | "Received inventory response for user {0} containing {1} folders and {2} items", | ||
459 | userID, response.Folders.Count, response.Items.Count); | ||
460 | callback = m_RequestingInventory[userID]; | ||
461 | m_RequestingInventory.Remove(userID); | ||
462 | } | ||
463 | else | ||
464 | { | ||
465 | m_log.WarnFormat( | ||
466 | "[HGrid INVENTORY SERVICE]: " + | ||
467 | "Received inventory response for {0} for which we do not have a record of requesting!", | ||
468 | userID); | ||
469 | return; | ||
470 | } | ||
471 | } | ||
455 | 472 | ||
456 | InventoryFolderImpl rootFolder = null; | 473 | InventoryFolderImpl rootFolder = null; |
457 | InventoryReceiptCallback callback = m_RequestingInventory[userID]; | ||
458 | 474 | ||
459 | ICollection<InventoryFolderImpl> folders = new List<InventoryFolderImpl>(); | 475 | ICollection<InventoryFolderImpl> folders = new List<InventoryFolderImpl>(); |
460 | ICollection<InventoryItemBase> items = new List<InventoryItemBase>(); | 476 | ICollection<InventoryItemBase> items = new List<InventoryItemBase>(); |
461 | 477 | ||
462 | foreach (InventoryFolderBase folder in response.Folders) | 478 | foreach (InventoryFolderBase folder in response.Folders) |
479 | { | ||
480 | if (folder.ParentID == UUID.Zero) | ||
463 | { | 481 | { |
464 | if (folder.ParentID == UUID.Zero) | 482 | rootFolder = new InventoryFolderImpl(folder); |
465 | { | 483 | folders.Add(rootFolder); |
466 | rootFolder = new InventoryFolderImpl(folder); | ||
467 | folders.Add(rootFolder); | ||
468 | 484 | ||
469 | break; | 485 | break; |
470 | } | ||
471 | } | 486 | } |
487 | } | ||
472 | 488 | ||
473 | if (rootFolder != null) | 489 | if (rootFolder != null) |
490 | { | ||
491 | foreach (InventoryFolderBase folder in response.Folders) | ||
474 | { | 492 | { |
475 | foreach (InventoryFolderBase folder in response.Folders) | 493 | if (folder.ID != rootFolder.ID) |
476 | { | ||
477 | if (folder.ID != rootFolder.ID) | ||
478 | { | ||
479 | folders.Add(new InventoryFolderImpl(folder)); | ||
480 | } | ||
481 | } | ||
482 | |||
483 | foreach (InventoryItemBase item in response.Items) | ||
484 | { | 494 | { |
485 | items.Add(item); | 495 | folders.Add(new InventoryFolderImpl(folder)); |
486 | } | 496 | } |
487 | } | 497 | } |
488 | else | 498 | |
499 | foreach (InventoryItemBase item in response.Items) | ||
489 | { | 500 | { |
490 | m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: Did not get back an inventory containing a root folder for user {0}", userID); | 501 | items.Add(item); |
491 | } | 502 | } |
492 | |||
493 | m_RequestingInventory.Remove(userID); | ||
494 | callback(folders, items); | ||
495 | |||
496 | } | 503 | } |
497 | else | 504 | else |
498 | { | 505 | { |
499 | m_log.WarnFormat( | 506 | m_log.ErrorFormat("[HGrid INVENTORY SERVICE]: Did not get back an inventory containing a root folder for user {0}", userID); |
500 | "[HGrid INVENTORY SERVICE]: " + | ||
501 | "Received inventory response for {0} for which we do not have a record of requesting!", | ||
502 | userID); | ||
503 | } | 507 | } |
504 | } | ||
505 | 508 | ||
509 | callback(folders, items); | ||
510 | |||
511 | } | ||
506 | 512 | ||
507 | private bool IsLocalStandaloneUser(UUID userID) | 513 | private bool IsLocalStandaloneUser(UUID userID) |
508 | { | 514 | { |
diff --git a/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs b/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs index 03fb0d5..e24f820 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1SecureInventoryService.cs | |||
@@ -69,34 +69,36 @@ namespace OpenSim.Region.Communications.OGS1 | |||
69 | /// <param name="callback"></param> | 69 | /// <param name="callback"></param> |
70 | public void RequestInventoryForUser(UUID userID, UUID session_id, InventoryReceiptCallback callback) | 70 | public void RequestInventoryForUser(UUID userID, UUID session_id, InventoryReceiptCallback callback) |
71 | { | 71 | { |
72 | if (!m_RequestingInventory.ContainsKey(userID)) | 72 | lock (m_RequestingInventory) |
73 | { | 73 | { |
74 | m_RequestingInventory.Add(userID, callback); | 74 | if (!m_RequestingInventory.ContainsKey(userID)) |
75 | 75 | m_RequestingInventory.Add(userID, callback); | |
76 | try | 76 | else |
77 | { | 77 | { |
78 | m_log.InfoFormat( | 78 | m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: RequestInventoryForUser() - could you not find user profile for {0}", userID); |
79 | "[OGS1 INVENTORY SERVICE]: Requesting inventory from {0}/GetInventory/ for user {1}", | 79 | return; |
80 | _inventoryServerUrl, userID); | 80 | } |
81 | } | ||
81 | 82 | ||
82 | RestSessionObjectPosterResponse<Guid, InventoryCollection> requester | 83 | try |
83 | = new RestSessionObjectPosterResponse<Guid, InventoryCollection>(); | 84 | { |
84 | requester.ResponseCallback = InventoryResponse; | 85 | m_log.InfoFormat( |
86 | "[OGS1 INVENTORY SERVICE]: Requesting inventory from {0}/GetInventory/ for user {1}", | ||
87 | _inventoryServerUrl, userID); | ||
85 | 88 | ||
86 | requester.BeginPostObject(_inventoryServerUrl + "/GetInventory/", userID.Guid, session_id.ToString(), userID.ToString()); | 89 | RestSessionObjectPosterResponse<Guid, InventoryCollection> requester |
87 | } | 90 | = new RestSessionObjectPosterResponse<Guid, InventoryCollection>(); |
88 | catch (WebException e) | 91 | requester.ResponseCallback = InventoryResponse; |
89 | { | ||
90 | if (StatsManager.SimExtraStats != null) | ||
91 | StatsManager.SimExtraStats.AddInventoryServiceRetrievalFailure(); | ||
92 | 92 | ||
93 | m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: Request inventory operation failed, {0} {1}", | 93 | requester.BeginPostObject(_inventoryServerUrl + "/GetInventory/", userID.Guid, session_id.ToString(), userID.ToString()); |
94 | e.Source, e.Message); | ||
95 | } | ||
96 | } | 94 | } |
97 | else | 95 | catch (WebException e) |
98 | { | 96 | { |
99 | m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: RequestInventoryForUser() - could you not find user profile for {0}", userID); | 97 | if (StatsManager.SimExtraStats != null) |
98 | StatsManager.SimExtraStats.AddInventoryServiceRetrievalFailure(); | ||
99 | |||
100 | m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: Request inventory operation failed, {0} {1}", | ||
101 | e.Source, e.Message); | ||
100 | } | 102 | } |
101 | } | 103 | } |
102 | 104 | ||
@@ -107,60 +109,66 @@ namespace OpenSim.Region.Communications.OGS1 | |||
107 | private void InventoryResponse(InventoryCollection response) | 109 | private void InventoryResponse(InventoryCollection response) |
108 | { | 110 | { |
109 | UUID userID = response.UserID; | 111 | UUID userID = response.UserID; |
110 | if (m_RequestingInventory.ContainsKey(userID)) | 112 | InventoryReceiptCallback callback = null; |
113 | lock (m_RequestingInventory) | ||
111 | { | 114 | { |
112 | m_log.InfoFormat("[OGS1 INVENTORY SERVICE]: " + | 115 | if (m_RequestingInventory.ContainsKey(userID)) |
113 | "Received inventory response for user {0} containing {1} folders and {2} items", | 116 | { |
114 | userID, response.Folders.Count, response.Items.Count); | 117 | callback = m_RequestingInventory[userID]; |
118 | m_RequestingInventory.Remove(userID); | ||
119 | } | ||
120 | else | ||
121 | { | ||
122 | m_log.WarnFormat( | ||
123 | "[OGS1 INVENTORY SERVICE]: " + | ||
124 | "Received inventory response for {0} for which we do not have a record of requesting!", | ||
125 | userID); | ||
126 | return; | ||
127 | } | ||
128 | } | ||
115 | 129 | ||
116 | InventoryFolderImpl rootFolder = null; | 130 | m_log.InfoFormat("[OGS1 INVENTORY SERVICE]: " + |
117 | InventoryReceiptCallback callback = m_RequestingInventory[userID]; | 131 | "Received inventory response for user {0} containing {1} folders and {2} items", |
132 | userID, response.Folders.Count, response.Items.Count); | ||
118 | 133 | ||
119 | ICollection<InventoryFolderImpl> folders = new List<InventoryFolderImpl>(); | 134 | InventoryFolderImpl rootFolder = null; |
120 | ICollection<InventoryItemBase> items = new List<InventoryItemBase>(); | ||
121 | 135 | ||
122 | foreach (InventoryFolderBase folder in response.Folders) | 136 | ICollection<InventoryFolderImpl> folders = new List<InventoryFolderImpl>(); |
137 | ICollection<InventoryItemBase> items = new List<InventoryItemBase>(); | ||
138 | |||
139 | foreach (InventoryFolderBase folder in response.Folders) | ||
140 | { | ||
141 | if (folder.ParentID == UUID.Zero) | ||
123 | { | 142 | { |
124 | if (folder.ParentID == UUID.Zero) | 143 | rootFolder = new InventoryFolderImpl(folder); |
125 | { | 144 | folders.Add(rootFolder); |
126 | rootFolder = new InventoryFolderImpl(folder); | ||
127 | folders.Add(rootFolder); | ||
128 | 145 | ||
129 | break; | 146 | break; |
130 | } | ||
131 | } | 147 | } |
148 | } | ||
132 | 149 | ||
133 | if (rootFolder != null) | 150 | if (rootFolder != null) |
151 | { | ||
152 | foreach (InventoryFolderBase folder in response.Folders) | ||
134 | { | 153 | { |
135 | foreach (InventoryFolderBase folder in response.Folders) | 154 | if (folder.ID != rootFolder.ID) |
136 | { | 155 | { |
137 | if (folder.ID != rootFolder.ID) | 156 | folders.Add(new InventoryFolderImpl(folder)); |
138 | { | ||
139 | folders.Add(new InventoryFolderImpl(folder)); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | foreach (InventoryItemBase item in response.Items) | ||
144 | { | ||
145 | items.Add(item); | ||
146 | } | 157 | } |
147 | } | 158 | } |
148 | else | 159 | |
160 | foreach (InventoryItemBase item in response.Items) | ||
149 | { | 161 | { |
150 | m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: Did not get back an inventory containing a root folder for user {0}", userID); | 162 | items.Add(item); |
151 | } | 163 | } |
152 | |||
153 | callback(folders, items); | ||
154 | |||
155 | m_RequestingInventory.Remove(userID); | ||
156 | } | 164 | } |
157 | else | 165 | else |
158 | { | 166 | { |
159 | m_log.WarnFormat( | 167 | m_log.ErrorFormat("[OGS1 INVENTORY SERVICE]: Did not get back an inventory containing a root folder for user {0}", userID); |
160 | "[OGS1 INVENTORY SERVICE]: " + | ||
161 | "Received inventory response for {0} for which we do not have a record of requesting!", | ||
162 | userID); | ||
163 | } | 168 | } |
169 | |||
170 | callback(folders, items); | ||
171 | |||
164 | } | 172 | } |
165 | 173 | ||
166 | /// <summary> | 174 | /// <summary> |