diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | 253 |
1 files changed, 155 insertions, 98 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index c3f6d6b..83d91c4 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Collections.Concurrent; | ||
30 | using System.IO; | 31 | using System.IO; |
31 | using System.Net; | 32 | using System.Net; |
32 | using System.Net.Mail; | 33 | using System.Net.Mail; |
@@ -94,18 +95,31 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
94 | { | 95 | { |
95 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 96 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
96 | 97 | ||
97 | private object HttpListLock = new object(); | 98 | private object m_httpListLock = new object(); |
98 | private int httpTimeout = 30000; | 99 | private int m_httpTimeout = 30000; |
99 | private string m_name = "HttpScriptRequests"; | 100 | private string m_name = "HttpScriptRequests"; |
100 | 101 | ||
101 | private OutboundUrlFilter m_outboundUrlFilter; | 102 | private OutboundUrlFilter m_outboundUrlFilter; |
102 | private string m_proxyurl = ""; | 103 | private string m_proxyurl = ""; |
103 | private string m_proxyexcepts = ""; | 104 | private string m_proxyexcepts = ""; |
104 | 105 | ||
106 | private float m_primPerSec = 1.0f; | ||
107 | private float m_primBurst = 3.0f; | ||
108 | private float m_primOwnerPerSec = 25.0f; | ||
109 | private float m_primOwnerBurst = 5.0f; | ||
110 | |||
111 | private struct ThrottleData | ||
112 | { | ||
113 | public double lastTime; | ||
114 | public float count; | ||
115 | } | ||
116 | |||
105 | // <request id, HttpRequestClass> | 117 | // <request id, HttpRequestClass> |
106 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; | 118 | private Dictionary<UUID, HttpRequestClass> m_pendingRequests; |
107 | private Scene m_scene; | 119 | private ConcurrentQueue<HttpRequestClass> m_CompletedRequests; |
108 | // private Queue<HttpRequestClass> rpcQueue = new Queue<HttpRequestClass>(); | 120 | private ConcurrentDictionary<uint, ThrottleData> m_RequestsThrottle; |
121 | private ConcurrentDictionary<UUID, ThrottleData> m_OwnerRequestsThrottle; | ||
122 | |||
109 | public static SmartThreadPool ThreadPool = null; | 123 | public static SmartThreadPool ThreadPool = null; |
110 | 124 | ||
111 | public HttpRequestModule() | 125 | public HttpRequestModule() |
@@ -119,10 +133,77 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
119 | return UUID.Zero; | 133 | return UUID.Zero; |
120 | } | 134 | } |
121 | 135 | ||
136 | public bool CheckThrottle(uint localID, UUID ownerID) | ||
137 | { | ||
138 | ThrottleData th; | ||
139 | double now = Util.GetTimeStamp(); | ||
140 | bool ret; | ||
141 | |||
142 | if (m_RequestsThrottle.TryGetValue(localID, out th)) | ||
143 | { | ||
144 | double delta = now - th.lastTime; | ||
145 | th.lastTime = now; | ||
146 | |||
147 | float add = (float)(m_primPerSec * delta); | ||
148 | th.count += add; | ||
149 | if (th.count > m_primBurst) | ||
150 | th.count = m_primBurst; | ||
151 | |||
152 | ret = th.count > 0; | ||
153 | if (ret) | ||
154 | th.count--; | ||
155 | } | ||
156 | else | ||
157 | { | ||
158 | th = new ThrottleData() | ||
159 | { | ||
160 | lastTime = now, | ||
161 | count = m_primBurst - 1 | ||
162 | }; | ||
163 | ret = true; | ||
164 | } | ||
165 | m_RequestsThrottle[localID] = th; | ||
166 | |||
167 | if(!ret) | ||
168 | return false; | ||
169 | |||
170 | if (m_OwnerRequestsThrottle.TryGetValue(ownerID, out th)) | ||
171 | { | ||
172 | double delta = now - th.lastTime; | ||
173 | th.lastTime = now; | ||
174 | |||
175 | float add = (float)(m_primOwnerPerSec * delta); | ||
176 | th.count += add; | ||
177 | if (th.count > m_primOwnerBurst) | ||
178 | th.count = m_primOwnerBurst; | ||
179 | |||
180 | ret = th.count > 0; | ||
181 | if (ret) | ||
182 | th.count--; | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | th = new ThrottleData() | ||
187 | { | ||
188 | lastTime = now, | ||
189 | count = m_primOwnerBurst - 1 | ||
190 | }; | ||
191 | } | ||
192 | m_OwnerRequestsThrottle[ownerID] = th; | ||
193 | |||
194 | return ret; | ||
195 | } | ||
196 | |||
122 | public UUID StartHttpRequest( | 197 | public UUID StartHttpRequest( |
123 | uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body, | 198 | uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body, |
124 | out HttpInitialRequestStatus status) | 199 | out HttpInitialRequestStatus status) |
125 | { | 200 | { |
201 | if (!CheckAllowed(new Uri(url))) | ||
202 | { | ||
203 | status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER; | ||
204 | return UUID.Zero; | ||
205 | } | ||
206 | |||
126 | UUID reqID = UUID.Random(); | 207 | UUID reqID = UUID.Random(); |
127 | HttpRequestClass htc = new HttpRequestClass(); | 208 | HttpRequestClass htc = new HttpRequestClass(); |
128 | 209 | ||
@@ -207,7 +288,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
207 | htc.ItemID = itemID; | 288 | htc.ItemID = itemID; |
208 | htc.Url = url; | 289 | htc.Url = url; |
209 | htc.ReqID = reqID; | 290 | htc.ReqID = reqID; |
210 | htc.HttpTimeout = httpTimeout; | 291 | htc.HttpTimeout = m_httpTimeout; |
211 | htc.OutboundBody = body; | 292 | htc.OutboundBody = body; |
212 | htc.ResponseHeaders = headers; | 293 | htc.ResponseHeaders = headers; |
213 | htc.proxyurl = m_proxyurl; | 294 | htc.proxyurl = m_proxyurl; |
@@ -216,16 +297,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
216 | // Same number as default HttpWebRequest.MaximumAutomaticRedirections | 297 | // Same number as default HttpWebRequest.MaximumAutomaticRedirections |
217 | htc.MaxRedirects = 50; | 298 | htc.MaxRedirects = 50; |
218 | 299 | ||
219 | if (StartHttpRequest(htc)) | 300 | lock (m_httpListLock) |
220 | { | 301 | m_pendingRequests.Add(reqID, htc); |
221 | status = HttpInitialRequestStatus.OK; | 302 | |
222 | return htc.ReqID; | 303 | htc.Process(); |
223 | } | 304 | status = HttpInitialRequestStatus.OK; |
224 | else | 305 | return reqID; |
225 | { | ||
226 | status = HttpInitialRequestStatus.DISALLOWED_BY_FILTER; | ||
227 | return UUID.Zero; | ||
228 | } | ||
229 | } | 306 | } |
230 | 307 | ||
231 | /// <summary> | 308 | /// <summary> |
@@ -237,34 +314,21 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
237 | return m_outboundUrlFilter.CheckAllowed(url); | 314 | return m_outboundUrlFilter.CheckAllowed(url); |
238 | } | 315 | } |
239 | 316 | ||
240 | public bool StartHttpRequest(HttpRequestClass req) | ||
241 | { | ||
242 | if (!CheckAllowed(new Uri(req.Url))) | ||
243 | return false; | ||
244 | |||
245 | lock (HttpListLock) | ||
246 | { | ||
247 | m_pendingRequests.Add(req.ReqID, req); | ||
248 | } | ||
249 | |||
250 | req.Process(); | ||
251 | |||
252 | return true; | ||
253 | } | ||
254 | |||
255 | public void StopHttpRequest(uint m_localID, UUID m_itemID) | 317 | public void StopHttpRequest(uint m_localID, UUID m_itemID) |
256 | { | 318 | { |
257 | if (m_pendingRequests != null) | 319 | List<UUID> toremove = new List<UUID>(); |
320 | lock (m_httpListLock) | ||
258 | { | 321 | { |
259 | lock (HttpListLock) | 322 | foreach (HttpRequestClass tmpReq in m_pendingRequests.Values) |
260 | { | 323 | { |
261 | HttpRequestClass tmpReq; | 324 | if(tmpReq.ItemID == m_itemID) |
262 | if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) | ||
263 | { | 325 | { |
264 | tmpReq.Stop(); | 326 | tmpReq.Stop(); |
265 | m_pendingRequests.Remove(m_itemID); | 327 | toremove.Add(tmpReq.ReqID); |
266 | } | 328 | } |
267 | } | 329 | } |
330 | foreach(UUID id in toremove) | ||
331 | m_pendingRequests.Remove(id); | ||
268 | } | 332 | } |
269 | } | 333 | } |
270 | 334 | ||
@@ -276,37 +340,35 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
276 | * finished. I thought about setting up a queue for this, but | 340 | * finished. I thought about setting up a queue for this, but |
277 | * it will need some refactoring and this works 'enough' right now | 341 | * it will need some refactoring and this works 'enough' right now |
278 | */ | 342 | */ |
343 | public void GotCompletedRequest(HttpRequestClass req) | ||
344 | { | ||
345 | lock (m_httpListLock) | ||
346 | { | ||
347 | if (req.Removed) | ||
348 | return; | ||
349 | m_pendingRequests.Remove(req.ReqID); | ||
350 | m_CompletedRequests.Enqueue(req); | ||
351 | } | ||
352 | } | ||
279 | 353 | ||
280 | public IServiceRequest GetNextCompletedRequest() | 354 | public IServiceRequest GetNextCompletedRequest() |
281 | { | 355 | { |
282 | lock (HttpListLock) | 356 | HttpRequestClass req; |
283 | { | 357 | if(m_CompletedRequests.TryDequeue(out req)) |
284 | foreach (UUID luid in m_pendingRequests.Keys) | 358 | return req; |
285 | { | ||
286 | HttpRequestClass tmpReq; | ||
287 | 359 | ||
288 | if (m_pendingRequests.TryGetValue(luid, out tmpReq)) | ||
289 | { | ||
290 | if (tmpReq.Finished) | ||
291 | { | ||
292 | return tmpReq; | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | return null; | 360 | return null; |
298 | } | 361 | } |
299 | 362 | ||
300 | public void RemoveCompletedRequest(UUID id) | 363 | public void RemoveCompletedRequest(UUID reqId) |
301 | { | 364 | { |
302 | lock (HttpListLock) | 365 | lock (m_httpListLock) |
303 | { | 366 | { |
304 | HttpRequestClass tmpReq; | 367 | HttpRequestClass tmpReq; |
305 | if (m_pendingRequests.TryGetValue(id, out tmpReq)) | 368 | if (m_pendingRequests.TryGetValue(reqId, out tmpReq)) |
306 | { | 369 | { |
307 | tmpReq.Stop(); | 370 | tmpReq.Stop(); |
308 | tmpReq = null; | 371 | m_pendingRequests.Remove(reqId); |
309 | m_pendingRequests.Remove(id); | ||
310 | } | 372 | } |
311 | } | 373 | } |
312 | } | 374 | } |
@@ -322,17 +384,28 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
322 | 384 | ||
323 | HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384); | 385 | HttpRequestClass.HttpBodyMaxLenMAX = config.Configs["Network"].GetInt("HttpBodyMaxLenMAX", 16384); |
324 | 386 | ||
325 | |||
326 | m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); | 387 | m_outboundUrlFilter = new OutboundUrlFilter("Script HTTP request module", config); |
327 | int maxThreads = 15; | ||
328 | 388 | ||
329 | IConfig httpConfig = config.Configs["HttpRequestModule"]; | 389 | int maxThreads = 8; |
390 | IConfig httpConfig = config.Configs["ScriptsHttpRequestModule"]; | ||
330 | if (httpConfig != null) | 391 | if (httpConfig != null) |
331 | { | 392 | { |
332 | maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); | 393 | maxThreads = httpConfig.GetInt("MaxPoolThreads", maxThreads); |
394 | m_primBurst = httpConfig.GetFloat("PrimRequestsBurst", m_primBurst); | ||
395 | m_primPerSec = httpConfig.GetFloat("PrimRequestsPerSec", m_primPerSec); | ||
396 | m_primOwnerBurst = httpConfig.GetFloat("PrimOwnerRequestsBurst", m_primOwnerBurst); | ||
397 | m_primOwnerPerSec = httpConfig.GetFloat("PrimOwnerRequestsPerSec", m_primOwnerPerSec); | ||
398 | m_httpTimeout = httpConfig.GetInt("RequestsTimeOut", m_httpTimeout); | ||
399 | if(m_httpTimeout > 60000) | ||
400 | m_httpTimeout = 60000; | ||
401 | else if(m_httpTimeout < 200) | ||
402 | m_httpTimeout = 200; | ||
333 | } | 403 | } |
334 | 404 | ||
335 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); | 405 | m_pendingRequests = new Dictionary<UUID, HttpRequestClass>(); |
406 | m_CompletedRequests = new ConcurrentQueue<HttpRequestClass>(); | ||
407 | m_RequestsThrottle = new ConcurrentDictionary<uint, ThrottleData>(); | ||
408 | m_OwnerRequestsThrottle = new ConcurrentDictionary<UUID, ThrottleData>(); | ||
336 | 409 | ||
337 | // First instance sets this up for all sims | 410 | // First instance sets this up for all sims |
338 | if (ThreadPool == null) | 411 | if (ThreadPool == null) |
@@ -352,16 +425,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
352 | 425 | ||
353 | public void AddRegion(Scene scene) | 426 | public void AddRegion(Scene scene) |
354 | { | 427 | { |
355 | m_scene = scene; | 428 | scene.RegisterModuleInterface<IHttpRequestModule>(this); |
356 | |||
357 | m_scene.RegisterModuleInterface<IHttpRequestModule>(this); | ||
358 | } | 429 | } |
359 | 430 | ||
360 | public void RemoveRegion(Scene scene) | 431 | public void RemoveRegion(Scene scene) |
361 | { | 432 | { |
362 | scene.UnregisterModuleInterface<IHttpRequestModule>(this); | 433 | scene.UnregisterModuleInterface<IHttpRequestModule>(this); |
363 | if (scene == m_scene) | ||
364 | m_scene = null; | ||
365 | } | 434 | } |
366 | 435 | ||
367 | public void PostInitialise() | 436 | public void PostInitialise() |
@@ -406,11 +475,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
406 | /// </summary> | 475 | /// </summary> |
407 | public HttpRequestModule RequestModule { get; set; } | 476 | public HttpRequestModule RequestModule { get; set; } |
408 | 477 | ||
409 | private bool _finished; | 478 | public bool Finished { get; private set;} |
410 | public bool Finished | 479 | public bool Removed{ get; set;} |
411 | { | ||
412 | get { return _finished; } | ||
413 | } | ||
414 | 480 | ||
415 | public static int HttpBodyMaxLenMAX = 16384; | 481 | public static int HttpBodyMaxLenMAX = 16384; |
416 | 482 | ||
@@ -427,19 +493,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
427 | public bool HttpPragmaNoCache = true; | 493 | public bool HttpPragmaNoCache = true; |
428 | 494 | ||
429 | // Request info | 495 | // Request info |
430 | private UUID _itemID; | 496 | public UUID ReqID { get; set; } |
431 | public UUID ItemID | 497 | public UUID ItemID { get; set;} |
432 | { | 498 | public uint LocalID { get; set;} |
433 | get { return _itemID; } | 499 | |
434 | set { _itemID = value; } | ||
435 | } | ||
436 | private uint _localID; | ||
437 | public uint LocalID | ||
438 | { | ||
439 | get { return _localID; } | ||
440 | set { _localID = value; } | ||
441 | } | ||
442 | public DateTime Next; | ||
443 | public string proxyurl; | 500 | public string proxyurl; |
444 | public string proxyexcepts; | 501 | public string proxyexcepts; |
445 | 502 | ||
@@ -454,12 +511,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
454 | public int MaxRedirects { get; set; } | 511 | public int MaxRedirects { get; set; } |
455 | 512 | ||
456 | public string OutboundBody; | 513 | public string OutboundBody; |
457 | private UUID _reqID; | 514 | |
458 | public UUID ReqID | ||
459 | { | ||
460 | get { return _reqID; } | ||
461 | set { _reqID = value; } | ||
462 | } | ||
463 | public HttpWebRequest Request; | 515 | public HttpWebRequest Request; |
464 | public string ResponseBody; | 516 | public string ResponseBody; |
465 | public List<string> ResponseMetadata; | 517 | public List<string> ResponseMetadata; |
@@ -469,10 +521,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
469 | 521 | ||
470 | public void Process() | 522 | public void Process() |
471 | { | 523 | { |
472 | _finished = false; | 524 | WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); |
473 | |||
474 | lock (HttpRequestModule.ThreadPool) | ||
475 | WorkItem = HttpRequestModule.ThreadPool.QueueWorkItem(new WorkItemCallback(StpSendWrapper), null); | ||
476 | } | 525 | } |
477 | 526 | ||
478 | private object StpSendWrapper(object o) | 527 | private object StpSendWrapper(object o) |
@@ -521,6 +570,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
521 | 570 | ||
522 | public void SendRequest() | 571 | public void SendRequest() |
523 | { | 572 | { |
573 | if(Removed) | ||
574 | return; | ||
575 | |||
524 | HttpWebResponse response = null; | 576 | HttpWebResponse response = null; |
525 | Stream resStream = null; | 577 | Stream resStream = null; |
526 | byte[] buf = new byte[HttpBodyMaxLenMAX + 16]; | 578 | byte[] buf = new byte[HttpBodyMaxLenMAX + 16]; |
@@ -534,6 +586,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
534 | 586 | ||
535 | Request.AllowAutoRedirect = false; | 587 | Request.AllowAutoRedirect = false; |
536 | Request.KeepAlive = false; | 588 | Request.KeepAlive = false; |
589 | Request.Timeout = HttpTimeout; | ||
537 | 590 | ||
538 | //This works around some buggy HTTP Servers like Lighttpd | 591 | //This works around some buggy HTTP Servers like Lighttpd |
539 | Request.ServicePoint.Expect100Continue = false; | 592 | Request.ServicePoint.Expect100Continue = false; |
@@ -593,7 +646,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
593 | bstream.Write(data, 0, data.Length); | 646 | bstream.Write(data, 0, data.Length); |
594 | } | 647 | } |
595 | 648 | ||
596 | Request.Timeout = HttpTimeout; | ||
597 | try | 649 | try |
598 | { | 650 | { |
599 | // execute the request | 651 | // execute the request |
@@ -672,7 +724,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
672 | if (response != null) | 724 | if (response != null) |
673 | response.Close(); | 725 | response.Close(); |
674 | 726 | ||
675 | |||
676 | // We need to resubmit | 727 | // We need to resubmit |
677 | if ( | 728 | if ( |
678 | (Status == (int)HttpStatusCode.MovedPermanently | 729 | (Status == (int)HttpStatusCode.MovedPermanently |
@@ -684,7 +735,8 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
684 | { | 735 | { |
685 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 736 | Status = (int)OSHttpStatusCode.ClientErrorJoker; |
686 | ResponseBody = "Number of redirects exceeded max redirects"; | 737 | ResponseBody = "Number of redirects exceeded max redirects"; |
687 | _finished = true; | 738 | WorkItem = null; |
739 | RequestModule.GotCompletedRequest(this); | ||
688 | } | 740 | } |
689 | else | 741 | else |
690 | { | 742 | { |
@@ -694,13 +746,15 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
694 | { | 746 | { |
695 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 747 | Status = (int)OSHttpStatusCode.ClientErrorJoker; |
696 | ResponseBody = "HTTP redirect code but no location header"; | 748 | ResponseBody = "HTTP redirect code but no location header"; |
697 | _finished = true; | 749 | WorkItem = null; |
750 | RequestModule.GotCompletedRequest(this); | ||
698 | } | 751 | } |
699 | else if (!RequestModule.CheckAllowed(new Uri(location))) | 752 | else if (!RequestModule.CheckAllowed(new Uri(location))) |
700 | { | 753 | { |
701 | Status = (int)OSHttpStatusCode.ClientErrorJoker; | 754 | Status = (int)OSHttpStatusCode.ClientErrorJoker; |
702 | ResponseBody = "URL from HTTP redirect blocked: " + location; | 755 | ResponseBody = "URL from HTTP redirect blocked: " + location; |
703 | _finished = true; | 756 | WorkItem = null; |
757 | RequestModule.GotCompletedRequest(this); | ||
704 | } | 758 | } |
705 | else | 759 | else |
706 | { | 760 | { |
@@ -717,9 +771,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
717 | } | 771 | } |
718 | else | 772 | else |
719 | { | 773 | { |
720 | _finished = true; | 774 | WorkItem = null; |
721 | if (ResponseBody == null) | 775 | if (ResponseBody == null) |
722 | ResponseBody = String.Empty; | 776 | ResponseBody = String.Empty; |
777 | RequestModule.GotCompletedRequest(this); | ||
723 | } | 778 | } |
724 | } | 779 | } |
725 | } | 780 | } |
@@ -728,10 +783,12 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest | |||
728 | { | 783 | { |
729 | try | 784 | try |
730 | { | 785 | { |
786 | Removed = true; | ||
787 | if(WorkItem == null) | ||
788 | return; | ||
789 | |||
731 | if (!WorkItem.Cancel()) | 790 | if (!WorkItem.Cancel()) |
732 | { | ||
733 | WorkItem.Cancel(true); | 791 | WorkItem.Cancel(true); |
734 | } | ||
735 | } | 792 | } |
736 | catch (Exception) | 793 | catch (Exception) |
737 | { | 794 | { |