For all Util.FireAndForget invocations, set thread to en_US before continuing wtih the invocation.

This is to avoid bugs where the locale is not manually set on the thread and bad data values get sent to the database or over the wire.
Lots of code does this manually but as we've seen, a subtle change can hit code which has forgotton to do this.
Since en_US show be used throughout the server at present, setting it at FireAndForget seems reasonable.
Arguably, it would be better to do this where data is sent, but doing it here is much easier.
All the manual BeginInvokes() remaining in the code should probably call FireAndForget instead.
bulletsim
Justin Clark-Casey (justincc) 2011-07-29 23:21:57 +01:00
parent 84c68c61bd
commit 9a5e0ede7c
1 changed files with 10 additions and 5 deletions

View File

@ -1499,25 +1499,30 @@ namespace OpenSim.Framework
public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
{
// When OpenSim interacts with a database or sends data over the wire, it must send this in en_US culture
// so that we don't encounter problems where, for instance, data is saved with a culture that uses commas
// for decimals places but is read by a culture that treats commas as number seperators.
WaitCallback realCallback = delegate(object o) { Culture.SetCurrentCulture(); callback(o); };
switch (FireAndForgetMethod)
{
case FireAndForgetMethod.UnsafeQueueUserWorkItem:
ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj);
break;
case FireAndForgetMethod.QueueUserWorkItem:
ThreadPool.QueueUserWorkItem(callback, obj);
ThreadPool.QueueUserWorkItem(realCallback, obj);
break;
case FireAndForgetMethod.BeginInvoke:
FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
wrapper.FireAndForget(callback, obj);
wrapper.FireAndForget(realCallback, obj);
break;
case FireAndForgetMethod.SmartThreadPool:
if (m_ThreadPool == null)
m_ThreadPool = new SmartThreadPool(2000, 15, 2);
m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { callback, obj });
m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj });
break;
case FireAndForgetMethod.Thread:
Thread thread = new Thread(delegate(object o) { callback(o); });
Thread thread = new Thread(delegate(object o) { realCallback(o); });
thread.Start(obj);
break;
default: