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
parent
84c68c61bd
commit
9a5e0ede7c
|
@ -1499,25 +1499,30 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
|
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)
|
switch (FireAndForgetMethod)
|
||||||
{
|
{
|
||||||
case FireAndForgetMethod.UnsafeQueueUserWorkItem:
|
case FireAndForgetMethod.UnsafeQueueUserWorkItem:
|
||||||
ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
|
ThreadPool.UnsafeQueueUserWorkItem(realCallback, obj);
|
||||||
break;
|
break;
|
||||||
case FireAndForgetMethod.QueueUserWorkItem:
|
case FireAndForgetMethod.QueueUserWorkItem:
|
||||||
ThreadPool.QueueUserWorkItem(callback, obj);
|
ThreadPool.QueueUserWorkItem(realCallback, obj);
|
||||||
break;
|
break;
|
||||||
case FireAndForgetMethod.BeginInvoke:
|
case FireAndForgetMethod.BeginInvoke:
|
||||||
FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
|
FireAndForgetWrapper wrapper = FireAndForgetWrapper.Instance;
|
||||||
wrapper.FireAndForget(callback, obj);
|
wrapper.FireAndForget(realCallback, obj);
|
||||||
break;
|
break;
|
||||||
case FireAndForgetMethod.SmartThreadPool:
|
case FireAndForgetMethod.SmartThreadPool:
|
||||||
if (m_ThreadPool == null)
|
if (m_ThreadPool == null)
|
||||||
m_ThreadPool = new SmartThreadPool(2000, 15, 2);
|
m_ThreadPool = new SmartThreadPool(2000, 15, 2);
|
||||||
m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { callback, obj });
|
m_ThreadPool.QueueWorkItem(SmartThreadPoolCallback, new object[] { realCallback, obj });
|
||||||
break;
|
break;
|
||||||
case FireAndForgetMethod.Thread:
|
case FireAndForgetMethod.Thread:
|
||||||
Thread thread = new Thread(delegate(object o) { callback(o); });
|
Thread thread = new Thread(delegate(object o) { realCallback(o); });
|
||||||
thread.Start(obj);
|
thread.Start(obj);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in New Issue