2007-07-16 15:40:11 +00:00
/ *
2008-03-18 05:16:43 +00:00
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-03-18 05:16:43 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2007-07-16 15:40:11 +00:00
using System ;
2008-12-09 03:06:26 +00:00
using System.IO ;
2012-09-30 14:57:49 +00:00
using System.Net ;
2008-10-04 20:27:55 +00:00
using System.Reflection ;
using log4net ;
2008-04-21 07:09:17 +00:00
using log4net.Config ;
2007-08-04 18:15:48 +00:00
using Nini.Config ;
2007-09-25 01:20:30 +00:00
using OpenSim.Framework ;
2007-10-30 09:05:31 +00:00
using OpenSim.Framework.Console ;
2007-07-16 15:40:11 +00:00
namespace OpenSim
{
2009-08-13 02:54:57 +00:00
/// <summary>
/// Starting class for the OpenSimulator Region
/// </summary>
2007-07-16 15:40:11 +00:00
public class Application
2007-10-30 09:05:31 +00:00
{
2009-08-13 02:54:57 +00:00
/// <summary>
/// Text Console Logger
/// </summary>
2008-10-04 20:27:55 +00:00
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2009-03-10 20:27:41 +00:00
2009-08-13 02:54:57 +00:00
/// <summary>
/// Path to the main ini Configuration file
/// </summary>
2008-02-01 23:56:09 +00:00
public static string iniFilePath = "" ;
2009-08-13 02:54:57 +00:00
/// <summary>
/// Save Crashes in the bin/crashes folder. Configurable with m_crashDir
/// </summary>
2008-12-09 03:06:26 +00:00
public static bool m_saveCrashDumps = false ;
2009-08-13 02:54:57 +00:00
/// <summary>
/// Directory to save crash reports to. Relative to bin/
/// </summary>
2008-12-09 03:06:26 +00:00
public static string m_crashDir = "crashes" ;
2009-08-13 02:54:57 +00:00
/// <summary>
/// Instance of the OpenSim class. This could be OpenSim or OpenSimBackground depending on the configuration
/// </summary>
2009-02-07 12:25:39 +00:00
protected static OpenSimBase m_sim = null ;
2007-07-16 15:40:11 +00:00
//could move our main function into OpenSimMain and kill this class
public static void Main ( string [ ] args )
{
2009-08-13 02:54:57 +00:00
// First line, hook the appdomain to the crash reporter
2009-03-10 20:27:41 +00:00
AppDomain . CurrentDomain . UnhandledException + =
new UnhandledExceptionEventHandler ( CurrentDomain_UnhandledException ) ;
2008-01-12 01:25:35 +00:00
2012-09-30 14:49:51 +00:00
ServicePointManager . DefaultConnectionLimit = 12 ;
2011-07-29 22:43:35 +00:00
2009-08-13 02:54:57 +00:00
// Add the arguments supplied when running the application to the configuration
2009-04-03 12:47:56 +00:00
ArgvConfigSource configSource = new ArgvConfigSource ( args ) ;
2009-08-13 02:54:57 +00:00
// Configure Log4Net
2009-04-03 12:47:56 +00:00
configSource . AddSwitch ( "Startup" , "logconfig" ) ;
string logConfigFile = configSource . Configs [ "Startup" ] . GetString ( "logconfig" , String . Empty ) ;
if ( logConfigFile ! = String . Empty )
{
XmlConfigurator . Configure ( new System . IO . FileInfo ( logConfigFile ) ) ;
m_log . InfoFormat ( "[OPENSIM MAIN]: configured log4net using \"{0}\" as configuration file" ,
logConfigFile ) ;
}
else
{
XmlConfigurator . Configure ( ) ;
m_log . Info ( "[OPENSIM MAIN]: configured log4net using default OpenSim.exe.config" ) ;
}
2008-02-11 09:11:33 +00:00
2012-07-05 23:37:45 +00:00
m_log . InfoFormat (
2011-07-29 22:43:35 +00:00
"[OPENSIM MAIN]: System Locale is {0}" , System . Threading . Thread . CurrentThread . CurrentCulture ) ;
2012-07-05 23:37:45 +00:00
string monoThreadsPerCpu = System . Environment . GetEnvironmentVariable ( "MONO_THREADS_PER_CPU" ) ;
m_log . InfoFormat (
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}" , monoThreadsPerCpu ? ? "unset" ) ;
2009-10-06 22:51:56 +00:00
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
int workerThreads , iocpThreads ;
System . Threading . ThreadPool . GetMaxThreads ( out workerThreads , out iocpThreads ) ;
m_log . InfoFormat ( "[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads" , workerThreads , iocpThreads ) ;
if ( workerThreads < 500 | | iocpThreads < 1000 )
{
workerThreads = 500 ;
iocpThreads = 1000 ;
m_log . Info ( "[OPENSIM MAIN]: Bumping up to 500 worker threads and 1000 IOCP threads" ) ;
System . Threading . ThreadPool . SetMaxThreads ( workerThreads , iocpThreads ) ;
}
2009-09-30 16:00:09 +00:00
// Check if the system is compatible with OpenSimulator.
2009-08-13 02:54:57 +00:00
// Ensures that the minimum system requirements are met
2008-01-15 02:09:55 +00:00
string supported = String . Empty ;
2007-10-30 09:05:31 +00:00
if ( Util . IsEnvironmentSupported ( ref supported ) )
2007-07-29 07:24:20 +00:00
{
2009-02-22 20:52:55 +00:00
m_log . Info ( "Environment is compatible.\n" ) ;
2007-07-29 07:24:20 +00:00
}
else
{
2009-02-22 20:52:55 +00:00
m_log . Warn ( "Environment is unsupported (" + supported + ")\n" ) ;
2007-07-29 07:24:20 +00:00
}
2007-10-30 09:05:31 +00:00
2009-08-13 02:54:57 +00:00
// Configure nIni aliases and localles
2007-10-30 09:05:31 +00:00
Culture . SetCurrentCulture ( ) ;
2007-08-13 18:33:03 +00:00
2007-07-16 20:10:54 +00:00
2010-05-16 03:21:36 +00:00
// Validate that the user has the most basic configuration done
// If not, offer to do the most basic configuration for them warning them along the way of the importance of
// reading these files.
2010-05-16 05:47:53 +00:00
/ *
2010-05-16 03:21:36 +00:00
m_log . Info ( "Checking for reguired configuration...\n" ) ;
bool OpenSim_Ini = ( File . Exists ( Path . Combine ( Util . configDir ( ) , "OpenSim.ini" ) ) )
| | ( File . Exists ( Path . Combine ( Util . configDir ( ) , "opensim.ini" ) ) )
| | ( File . Exists ( Path . Combine ( Util . configDir ( ) , "openSim.ini" ) ) )
| | ( File . Exists ( Path . Combine ( Util . configDir ( ) , "Opensim.ini" ) ) ) ;
bool StanaloneCommon_ProperCased = File . Exists ( Path . Combine ( Path . Combine ( Util . configDir ( ) , "config-include" ) , "StandaloneCommon.ini" ) ) ;
bool StanaloneCommon_lowercased = File . Exists ( Path . Combine ( Path . Combine ( Util . configDir ( ) , "config-include" ) , "standalonecommon.ini" ) ) ;
bool GridCommon_ProperCased = File . Exists ( Path . Combine ( Path . Combine ( Util . configDir ( ) , "config-include" ) , "GridCommon.ini" ) ) ;
bool GridCommon_lowerCased = File . Exists ( Path . Combine ( Path . Combine ( Util . configDir ( ) , "config-include" ) , "gridcommon.ini" ) ) ;
if ( ( OpenSim_Ini )
& & (
( StanaloneCommon_ProperCased
| | StanaloneCommon_lowercased
| | GridCommon_ProperCased
| | GridCommon_lowerCased
) ) )
{
m_log . Info ( "Required Configuration Files Found\n" ) ;
}
else
{
MainConsole . Instance = new LocalConsole ( "Region" ) ;
string resp = MainConsole . Instance . CmdPrompt (
"\n\n*************Required Configuration files not found.*************\n\n OpenSimulator will not run without these files.\n\nRemember, these file names are Case Sensitive in Linux and Proper Cased.\n1. ./OpenSim.ini\nand\n2. ./config-include/StandaloneCommon.ini \nor\n3. ./config-include/GridCommon.ini\n\nAlso, you will want to examine these files in great detail because only the basic system will load by default. OpenSimulator can do a LOT more if you spend a little time going through these files.\n\n" + ": " + "Do you want to copy the most basic Defaults from standalone?" ,
"yes" ) ;
if ( resp = = "yes" )
{
if ( ! ( OpenSim_Ini ) )
{
try
{
File . Copy ( Path . Combine ( Util . configDir ( ) , "OpenSim.ini.example" ) ,
Path . Combine ( Util . configDir ( ) , "OpenSim.ini" ) ) ;
} catch ( UnauthorizedAccessException )
{
MainConsole . Instance . Output ( "Unable to Copy OpenSim.ini.example to OpenSim.ini, Make sure OpenSim has have the required permissions\n" ) ;
} catch ( ArgumentException )
{
MainConsole . Instance . Output ( "Unable to Copy OpenSim.ini.example to OpenSim.ini, The current directory is invalid.\n" ) ;
} catch ( System . IO . PathTooLongException )
{
MainConsole . Instance . Output ( "Unable to Copy OpenSim.ini.example to OpenSim.ini, the Path to these files is too long.\n" ) ;
} catch ( System . IO . DirectoryNotFoundException )
{
MainConsole . Instance . Output ( "Unable to Copy OpenSim.ini.example to OpenSim.ini, the current directory is reporting as not found.\n" ) ;
} catch ( System . IO . FileNotFoundException )
{
MainConsole . Instance . Output ( "Unable to Copy OpenSim.ini.example to OpenSim.ini, the example is not found, please make sure that the example files exist.\n" ) ;
} catch ( System . IO . IOException )
{
// Destination file exists already or a hard drive failure... .. so we can just drop this one
//MainConsole.Instance.Output("Unable to Copy OpenSim.ini.example to OpenSim.ini, the example is not found, please make sure that the example files exist.\n");
} catch ( System . NotSupportedException )
{
MainConsole . Instance . Output ( "Unable to Copy OpenSim.ini.example to OpenSim.ini, The current directory is invalid.\n" ) ;
}
}
if ( ! ( StanaloneCommon_ProperCased | | StanaloneCommon_lowercased ) )
{
try
{
File . Copy ( Path . Combine ( Path . Combine ( Util . configDir ( ) , "config-include" ) , "StandaloneCommon.ini.example" ) ,
Path . Combine ( Path . Combine ( Util . configDir ( ) , "config-include" ) , "StandaloneCommon.ini" ) ) ;
}
catch ( UnauthorizedAccessException )
{
MainConsole . Instance . Output ( "Unable to Copy StandaloneCommon.ini.example to StandaloneCommon.ini, Make sure OpenSim has the required permissions\n" ) ;
}
catch ( ArgumentException )
{
MainConsole . Instance . Output ( "Unable to Copy StandaloneCommon.ini.example to StandaloneCommon.ini, The current directory is invalid.\n" ) ;
}
catch ( System . IO . PathTooLongException )
{
MainConsole . Instance . Output ( "Unable to Copy StandaloneCommon.ini.example to StandaloneCommon.ini, the Path to these files is too long.\n" ) ;
}
catch ( System . IO . DirectoryNotFoundException )
{
MainConsole . Instance . Output ( "Unable to Copy StandaloneCommon.ini.example to StandaloneCommon.ini, the current directory is reporting as not found.\n" ) ;
}
catch ( System . IO . FileNotFoundException )
{
MainConsole . Instance . Output ( "Unable to Copy StandaloneCommon.ini.example to StandaloneCommon.ini, the example is not found, please make sure that the example files exist.\n" ) ;
}
catch ( System . IO . IOException )
{
// Destination file exists already or a hard drive failure... .. so we can just drop this one
//MainConsole.Instance.Output("Unable to Copy OpenSim.ini.example to OpenSim.ini, the example is not found, please make sure that the example files exist.\n");
}
catch ( System . NotSupportedException )
{
MainConsole . Instance . Output ( "Unable to Copy StandaloneCommon.ini.example to StandaloneCommon.ini, The current directory is invalid.\n" ) ;
}
}
}
MainConsole . Instance = null ;
2010-09-12 17:43:49 +00:00
}
2010-05-16 05:47:53 +00:00
* /
2008-04-28 14:41:46 +00:00
configSource . Alias . AddAlias ( "On" , true ) ;
configSource . Alias . AddAlias ( "Off" , false ) ;
configSource . Alias . AddAlias ( "True" , true ) ;
configSource . Alias . AddAlias ( "False" , false ) ;
2011-05-31 12:38:32 +00:00
configSource . Alias . AddAlias ( "Yes" , true ) ;
configSource . Alias . AddAlias ( "No" , false ) ;
2008-04-28 14:41:46 +00:00
configSource . AddSwitch ( "Startup" , "background" ) ;
2007-08-06 16:33:54 +00:00
configSource . AddSwitch ( "Startup" , "inifile" ) ;
2008-10-11 17:51:16 +00:00
configSource . AddSwitch ( "Startup" , "inimaster" ) ;
2009-02-27 14:17:57 +00:00
configSource . AddSwitch ( "Startup" , "inidirectory" ) ;
2007-08-06 16:33:54 +00:00
configSource . AddSwitch ( "Startup" , "physics" ) ;
2009-02-10 12:25:29 +00:00
configSource . AddSwitch ( "Startup" , "gui" ) ;
2009-08-17 08:21:39 +00:00
configSource . AddSwitch ( "Startup" , "console" ) ;
2011-05-31 13:24:51 +00:00
configSource . AddSwitch ( "Startup" , "save_crashes" ) ;
configSource . AddSwitch ( "Startup" , "crash_dir" ) ;
2007-07-16 18:37:31 +00:00
2007-10-26 15:00:35 +00:00
configSource . AddConfig ( "StandAlone" ) ;
configSource . AddConfig ( "Network" ) ;
2009-08-13 02:54:57 +00:00
// Check if we're running in the background or not
2008-04-28 14:41:46 +00:00
bool background = configSource . Configs [ "Startup" ] . GetBoolean ( "background" , false ) ;
2009-08-13 02:54:57 +00:00
// Check if we're saving crashes
2008-12-09 03:06:26 +00:00
m_saveCrashDumps = configSource . Configs [ "Startup" ] . GetBoolean ( "save_crashes" , false ) ;
2009-08-13 02:54:57 +00:00
// load Crash directory config
2011-04-07 23:42:35 +00:00
m_crashDir = configSource . Configs [ "Startup" ] . GetString ( "crash_dir" , m_crashDir ) ;
2010-05-16 03:21:36 +00:00
2008-04-28 14:41:46 +00:00
if ( background )
{
2009-02-07 12:25:39 +00:00
m_sim = new OpenSimBackground ( configSource ) ;
m_sim . Startup ( ) ;
2008-04-28 14:41:46 +00:00
}
else
2011-04-07 23:42:35 +00:00
{
2009-04-27 00:16:59 +00:00
m_sim = new OpenSim ( configSource ) ;
2011-04-07 23:42:35 +00:00
2009-02-07 12:25:39 +00:00
m_sim . Startup ( ) ;
2008-04-28 14:41:46 +00:00
while ( true )
{
2009-02-10 18:50:25 +00:00
try
{
2009-08-13 02:54:57 +00:00
// Block thread here for input
2009-02-10 18:50:25 +00:00
MainConsole . Instance . Prompt ( ) ;
}
catch ( Exception e )
{
2009-05-19 19:57:45 +00:00
m_log . ErrorFormat ( "Command error: {0}" , e ) ;
2009-02-10 18:50:25 +00:00
}
2008-04-28 14:41:46 +00:00
}
2007-07-16 15:40:11 +00:00
}
}
2008-01-12 01:25:35 +00:00
2008-01-18 23:45:16 +00:00
private static bool _IsHandlingException = false ; // Make sure we don't go recursive on ourself
2008-08-18 00:39:10 +00:00
2008-01-12 01:25:35 +00:00
/// <summary>
/// Global exception handler -- all unhandlet exceptions end up here :)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void CurrentDomain_UnhandledException ( object sender , UnhandledExceptionEventArgs e )
{
2008-01-18 23:45:16 +00:00
if ( _IsHandlingException )
2009-07-24 06:59:27 +00:00
{
2008-01-18 23:45:16 +00:00
return ;
2009-07-24 06:59:27 +00:00
}
2008-01-18 23:45:16 +00:00
_IsHandlingException = true ;
2008-01-12 01:25:35 +00:00
// TODO: Add config option to allow users to turn off error reporting
// TODO: Post error report (disabled for now)
2008-05-16 01:22:11 +00:00
2008-01-15 02:09:55 +00:00
string msg = String . Empty ;
2008-01-12 01:25:35 +00:00
msg + = "\r\n" ;
2008-01-14 18:02:37 +00:00
msg + = "APPLICATION EXCEPTION DETECTED: " + e . ToString ( ) + "\r\n" ;
2008-01-12 01:25:35 +00:00
msg + = "\r\n" ;
2008-01-14 18:02:37 +00:00
msg + = "Exception: " + e . ExceptionObject . ToString ( ) + "\r\n" ;
2009-03-10 20:27:41 +00:00
Exception ex = ( Exception ) e . ExceptionObject ;
2008-01-18 23:45:16 +00:00
if ( ex . InnerException ! = null )
2008-09-08 14:30:35 +00:00
{
2008-01-18 23:45:16 +00:00
msg + = "InnerException: " + ex . InnerException . ToString ( ) + "\r\n" ;
2008-09-08 14:30:35 +00:00
}
2008-01-18 23:45:16 +00:00
2008-01-14 18:02:37 +00:00
msg + = "\r\n" ;
2008-05-16 01:22:11 +00:00
msg + = "Application is terminating: " + e . IsTerminating . ToString ( ) + "\r\n" ;
2008-01-14 18:02:37 +00:00
2008-10-04 20:27:55 +00:00
m_log . ErrorFormat ( "[APPLICATION]: {0}" , msg ) ;
2008-01-12 01:30:57 +00:00
2009-06-01 18:45:36 +00:00
if ( m_saveCrashDumps )
2008-01-12 01:25:35 +00:00
{
2009-06-01 18:45:36 +00:00
// Log exception to disk
try
2008-12-09 03:06:26 +00:00
{
2009-06-01 18:45:36 +00:00
if ( ! Directory . Exists ( m_crashDir ) )
{
Directory . CreateDirectory ( m_crashDir ) ;
}
string log = Util . GetUniqueFilename ( ex . GetType ( ) + ".txt" ) ;
2009-10-04 20:57:51 +00:00
using ( StreamWriter m_crashLog = new StreamWriter ( Path . Combine ( m_crashDir , log ) ) )
{
m_crashLog . WriteLine ( msg ) ;
}
2009-01-04 19:09:22 +00:00
2009-06-01 18:45:36 +00:00
File . Copy ( "OpenSim.ini" , Path . Combine ( m_crashDir , log + "_OpenSim.ini" ) , true ) ;
}
catch ( Exception e2 )
{
m_log . ErrorFormat ( "[CRASH LOGGER CRASHED]: {0}" , e2 ) ;
}
2008-01-12 01:25:35 +00:00
}
2008-01-18 23:45:16 +00:00
2009-03-10 20:27:41 +00:00
_IsHandlingException = false ;
2008-01-12 01:25:35 +00:00
}
2007-07-16 15:40:11 +00:00
}
2009-08-17 08:21:39 +00:00
}