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.
Diffstat (limited to '')
-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> |