2016-04-21 15:19:32 +03:00
|
|
|
//
|
|
|
|
// main.m: Basic startup code for Mono on the iPhone
|
|
|
|
//
|
|
|
|
// Authors:
|
|
|
|
// Geoff Norton
|
|
|
|
// Rolf Bjarne Kvinge <rolf@xamarin.com>
|
|
|
|
//
|
|
|
|
// Copyright 2009 Novell, Inc.
|
|
|
|
// Copyright 2011-2012 Xamarin Inc.
|
|
|
|
//
|
|
|
|
|
2021-02-26 16:42:30 +03:00
|
|
|
#include <TargetConditionals.h>
|
|
|
|
#if !TARGET_OS_OSX
|
2016-04-21 15:19:32 +03:00
|
|
|
#include <UIKit/UIKit.h>
|
2021-02-26 16:42:30 +03:00
|
|
|
#endif
|
2016-04-21 15:19:32 +03:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <zlib.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <objc/message.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
|
|
|
#include "xamarin/xamarin.h"
|
|
|
|
#include "monotouch-debug.h"
|
|
|
|
|
|
|
|
#include "shared.h"
|
|
|
|
#include "product.h"
|
|
|
|
#include "runtime-internal.h"
|
|
|
|
#include "delegates.h"
|
|
|
|
|
2021-05-25 22:30:35 +03:00
|
|
|
#if defined(__x86_64__) && !DOTNET
|
2016-04-21 15:19:32 +03:00
|
|
|
#include "../tools/mtouch/monotouch-fixes.c"
|
|
|
|
#endif
|
|
|
|
|
2021-11-22 20:50:28 +03:00
|
|
|
static char original_working_directory_path [MAXPATHLEN];
|
|
|
|
|
|
|
|
const char * const
|
|
|
|
xamarin_get_original_working_directory_path ()
|
|
|
|
{
|
|
|
|
return original_working_directory_path;
|
|
|
|
}
|
|
|
|
|
2021-05-21 08:53:41 +03:00
|
|
|
#if !defined (CORECLR_RUNTIME)
|
2021-03-18 09:23:39 +03:00
|
|
|
unsigned char *
|
2016-04-21 15:19:32 +03:00
|
|
|
xamarin_load_aot_data (MonoAssembly *assembly, int size, gpointer user_data, void **out_handle)
|
|
|
|
{
|
2016-02-15 21:02:14 +03:00
|
|
|
// COOP: This is a callback called by the AOT runtime, I believe we don't have to change the GC mode here (even though it accesses managed memory).
|
2016-04-21 15:19:32 +03:00
|
|
|
*out_handle = NULL;
|
2016-12-12 20:57:02 +03:00
|
|
|
|
|
|
|
char path [1024];
|
|
|
|
char name [1024];
|
|
|
|
MonoAssemblyName *assembly_name = mono_assembly_get_name (assembly);
|
|
|
|
const char *aname = mono_assembly_name_get_name (assembly_name);
|
|
|
|
xamarin_get_assembly_name_without_extension (aname, name, sizeof (name));
|
|
|
|
|
|
|
|
// LOG (PRODUCT ": Looking for aot data for assembly '%s'.", name);
|
|
|
|
|
|
|
|
strlcat (name, ".aotdata", sizeof (name));
|
|
|
|
|
|
|
|
bool found = xamarin_locate_assembly_resource_for_name (assembly_name, name, path, sizeof (path));
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
LOG (PRODUCT ": Could not find the aot data for %s.\n", aname)
|
|
|
|
return NULL;
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int fd = open (path, O_RDONLY);
|
|
|
|
if (fd < 0) {
|
2016-12-12 20:57:02 +03:00
|
|
|
LOG (PRODUCT ": Could not load the aot data for %s from %s: %s\n", aname, path, strerror (errno));
|
2016-04-21 15:19:32 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-11-18 16:36:47 +03:00
|
|
|
void *ptr = mmap (NULL, (size_t) size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
|
2016-04-21 15:19:32 +03:00
|
|
|
if (ptr == MAP_FAILED) {
|
2016-12-12 20:57:02 +03:00
|
|
|
LOG (PRODUCT ": Could not map the aot file for %s: %s\n", aname, strerror (errno));
|
2016-04-21 15:19:32 +03:00
|
|
|
close (fd);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
close (fd);
|
|
|
|
|
2016-12-12 20:57:02 +03:00
|
|
|
//LOG (PRODUCT ": Loaded aot data for %s.\n", name);
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
*out_handle = ptr;
|
|
|
|
|
|
|
|
return (unsigned char *) ptr;
|
|
|
|
}
|
|
|
|
|
2021-03-18 09:23:39 +03:00
|
|
|
void
|
2016-04-21 15:19:32 +03:00
|
|
|
xamarin_free_aot_data (MonoAssembly *assembly, int size, gpointer user_data, void *handle)
|
|
|
|
{
|
2016-02-15 21:02:14 +03:00
|
|
|
// COOP: This is a callback called by the AOT runtime, I belive we don't have to change the GC mode here.
|
2019-11-18 16:36:47 +03:00
|
|
|
munmap (handle, (size_t) size);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This hook avoids the gazillion of filesystem probes we do as part of assembly loading.
|
|
|
|
*/
|
2021-03-18 09:23:39 +03:00
|
|
|
MonoAssembly*
|
|
|
|
xamarin_assembly_preload_hook (MonoAssemblyName *aname, char **assemblies_path, void* user_data)
|
2016-04-21 15:19:32 +03:00
|
|
|
{
|
2016-02-15 21:02:14 +03:00
|
|
|
// COOP: This is a callback called by the AOT runtime, I belive we don't have to change the GC mode here.
|
2016-04-21 15:19:32 +03:00
|
|
|
char filename [1024];
|
|
|
|
char path [1024];
|
|
|
|
const char *name = mono_assembly_name_get_name (aname);
|
|
|
|
const char *culture = mono_assembly_name_get_culture (aname);
|
2016-12-12 20:57:02 +03:00
|
|
|
|
|
|
|
// LOG (PRODUCT ": Looking for assembly '%s' (culture: '%s')\n", name, culture);
|
|
|
|
|
2020-06-19 16:36:02 +03:00
|
|
|
size_t len = strnlen (name, sizeof (filename));
|
|
|
|
if (len == sizeof (filename))
|
|
|
|
return NULL;
|
2016-04-21 15:19:32 +03:00
|
|
|
int has_extension = len > 3 && name [len - 4] == '.' && (!strcmp ("exe", name + (len - 3)) || !strcmp ("dll", name + (len - 3)));
|
|
|
|
bool dual_check = false;
|
|
|
|
|
|
|
|
// add extensions if required.
|
2017-01-04 20:10:47 +03:00
|
|
|
strlcpy (filename, name, sizeof (filename));
|
2016-04-21 15:19:32 +03:00
|
|
|
if (!has_extension) {
|
|
|
|
// Figure out if we need to append 'dll' or 'exe'
|
|
|
|
if (xamarin_executable_name != NULL) {
|
|
|
|
// xamarin_executable_name already has the ".exe", so only compare the rest of the filename.
|
2020-06-19 16:36:02 +03:00
|
|
|
size_t exe_len = strnlen (name, PATH_MAX);
|
|
|
|
if (exe_len == PATH_MAX)
|
|
|
|
return NULL;
|
|
|
|
if (culture == NULL && !strncmp (xamarin_executable_name, filename, exe_len - 4)) {
|
2017-01-04 20:10:47 +03:00
|
|
|
strlcat (filename, ".exe", sizeof (filename));
|
2016-04-21 15:19:32 +03:00
|
|
|
} else {
|
2017-01-04 20:10:47 +03:00
|
|
|
strlcat (filename, ".dll", sizeof (filename));
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// we need to check both :|
|
|
|
|
dual_check = true;
|
|
|
|
// start with .dll
|
2017-01-04 20:10:47 +03:00
|
|
|
strlcat (filename, ".dll", sizeof (filename));
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (culture == NULL)
|
|
|
|
culture = "";
|
|
|
|
|
2016-12-12 20:57:02 +03:00
|
|
|
bool found = xamarin_locate_assembly_resource_for_name (aname, filename, path, sizeof (path));
|
|
|
|
if (!found && dual_check) {
|
2020-06-19 16:36:02 +03:00
|
|
|
size_t flen = strnlen (filename, sizeof (filename));
|
|
|
|
if (flen == sizeof (filename))
|
|
|
|
return NULL;
|
|
|
|
filename [flen - 4] = 0;
|
2017-01-04 20:10:47 +03:00
|
|
|
strlcat (filename, ".exe", sizeof (filename));
|
2016-12-12 20:57:02 +03:00
|
|
|
found = xamarin_locate_assembly_resource_for_name (aname, filename, path, sizeof (path));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
LOG (PRODUCT ": Unable to locate assembly '%s' (culture: '%s')\n", name, culture);
|
|
|
|
return NULL;
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
2016-12-12 20:57:02 +03:00
|
|
|
// LOG (PRODUCT ": Found assembly '%s' (culture: '%s'): %s\n", name, culture, path);
|
2016-04-21 15:19:32 +03:00
|
|
|
|
2016-12-12 20:57:02 +03:00
|
|
|
return mono_assembly_open (path, NULL);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
2021-05-21 08:53:41 +03:00
|
|
|
#endif // !defined (CORECLR_RUNTIME)
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG_LAUNCH_TIME
|
2016-10-19 04:40:42 +03:00
|
|
|
uint64_t startDate = 0;
|
|
|
|
uint64_t date = 0;
|
2016-04-21 15:19:32 +03:00
|
|
|
void debug_launch_time_print (const char *msg)
|
|
|
|
{
|
2016-10-19 04:40:42 +03:00
|
|
|
uint64_t unow;
|
2016-04-21 15:19:32 +03:00
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
gettimeofday (&now, NULL);
|
|
|
|
unow = now.tv_sec * 1000000ULL + now.tv_usec;
|
|
|
|
|
|
|
|
if (startDate == 0) {
|
|
|
|
startDate = unow;
|
|
|
|
date = startDate;
|
|
|
|
}
|
|
|
|
|
2016-09-06 23:55:23 +03:00
|
|
|
PRINT ("%s: %llu us Total: %llu us", msg, unow - date, unow - startDate);
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
date = unow;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
inline void debug_launch_time_print (const char *msg)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This class will listen for memory warnings and when received, force
|
|
|
|
* a full garbage collection.
|
|
|
|
*
|
|
|
|
* On device it will also delay the creation of the finalizer thread for 5 seconds
|
|
|
|
* in release builds.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if defined (__arm__) || defined(__aarch64__)
|
2021-03-25 09:26:48 +03:00
|
|
|
#if !defined (CORECLR_RUNTIME)
|
2016-04-21 15:19:32 +03:00
|
|
|
extern void mono_gc_init_finalizer_thread (void);
|
|
|
|
#endif
|
2021-03-25 09:26:48 +03:00
|
|
|
#endif
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
@interface XamarinGCSupport : NSObject {
|
|
|
|
}
|
|
|
|
- (id) init;
|
|
|
|
- (void) start;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation XamarinGCSupport
|
|
|
|
- (id) init
|
|
|
|
{
|
|
|
|
if (self = [super init]) {
|
|
|
|
#if defined (__arm__) || defined(__aarch64__)
|
|
|
|
[self start];
|
|
|
|
#endif
|
2016-07-28 10:56:55 +03:00
|
|
|
#if TARGET_OS_WATCH
|
|
|
|
// I haven't found a way to listen for memory warnings on watchOS.
|
|
|
|
// fprintf (stderr, "Need to listen for memory warnings on the watch\n");
|
2021-02-26 16:42:30 +03:00
|
|
|
#elif !TARGET_OS_OSX
|
2016-04-21 15:19:32 +03:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(memoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
|
2016-07-28 10:56:55 +03:00
|
|
|
#endif
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) start
|
|
|
|
{
|
2016-02-15 21:02:14 +03:00
|
|
|
// COOP: ?
|
2016-04-21 15:19:32 +03:00
|
|
|
#if defined (__arm__) || defined(__aarch64__)
|
2021-03-25 09:26:48 +03:00
|
|
|
#if !defined (CORECLR_RUNTIME)
|
2020-03-31 10:28:02 +03:00
|
|
|
MONO_ENTER_GC_UNSAFE;
|
2016-04-21 15:19:32 +03:00
|
|
|
mono_gc_init_finalizer_thread ();
|
2020-03-31 10:28:02 +03:00
|
|
|
MONO_EXIT_GC_UNSAFE;
|
2016-04-21 15:19:32 +03:00
|
|
|
#endif
|
2021-03-25 09:26:48 +03:00
|
|
|
#endif
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void) memoryWarning: (NSNotification *) sender
|
|
|
|
{
|
2016-02-15 21:02:14 +03:00
|
|
|
// COOP: ?
|
2021-03-11 09:37:45 +03:00
|
|
|
GCHandle exception_gchandle = INVALID_GCHANDLE;
|
|
|
|
xamarin_gc_collect (&exception_gchandle);
|
|
|
|
xamarin_process_managed_exception_gchandle (exception_gchandle);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The main method
|
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
2017-04-10 07:48:35 +03:00
|
|
|
xamarin_main (int argc, char *argv[], enum XamarinLaunchMode launch_mode)
|
2016-04-21 15:19:32 +03:00
|
|
|
{
|
2016-02-15 21:02:14 +03:00
|
|
|
// COOP: ?
|
2016-04-21 15:19:32 +03:00
|
|
|
// + 1 for the initial "monotouch" +1 for the final NULL = +2.
|
|
|
|
// This is not an exact number (it will most likely be lower, since there
|
|
|
|
// are other arguments besides --app-arg), but it's a guaranteed and bound
|
|
|
|
// upper limit.
|
|
|
|
const char *managed_argv [argc + 2];
|
2021-05-27 17:42:09 +03:00
|
|
|
int managed_argc = 0;
|
2016-04-21 15:19:32 +03:00
|
|
|
|
2021-05-25 22:30:35 +03:00
|
|
|
#if defined(__x86_64__) && !DOTNET
|
2016-04-21 15:19:32 +03:00
|
|
|
patch_sigaction ();
|
|
|
|
#endif
|
|
|
|
|
2017-04-28 15:02:38 +03:00
|
|
|
xamarin_launch_mode = launch_mode;
|
2017-01-24 12:30:23 +03:00
|
|
|
|
2019-11-18 16:36:47 +03:00
|
|
|
memset (managed_argv, 0, sizeof (char*) * (unsigned long) (argc + 2));
|
2021-05-27 17:42:09 +03:00
|
|
|
|
|
|
|
#if !(TARGET_OS_OSX || TARGET_OS_MACCATALYST)
|
|
|
|
managed_argv [managed_argc++] = "monotouch";
|
|
|
|
#endif
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("Main entered");
|
|
|
|
|
|
|
|
xamarin_setup ();
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("MonoTouch setup time");
|
|
|
|
|
|
|
|
MonoAssembly *assembly;
|
2021-02-11 10:18:38 +03:00
|
|
|
GCHandle exception_gchandle = NULL;
|
2016-04-21 15:19:32 +03:00
|
|
|
|
2021-11-22 20:50:28 +03:00
|
|
|
// Get the original working directory, and store it somewhere.
|
|
|
|
if (getcwd (original_working_directory_path, sizeof (original_working_directory_path)) == NULL)
|
|
|
|
original_working_directory_path [0] = '\0';
|
|
|
|
|
2021-07-14 18:42:49 +03:00
|
|
|
// For legacy Xamarin.Mac, we used to chdir to $appdir/Contents/Resources (I'm not sure where this comes from, earliest commit I could find was this: https://github.com/xamarin/maccore/commit/20045dd7f85cb038cea673a9281bb6131711069c)
|
|
|
|
// For mobile platforms, we chdir to $appdir
|
|
|
|
// In .NET, we always chdir to $appdir, so that we're consistent
|
|
|
|
const char *c_bundle_path = xamarin_get_app_bundle_path ();
|
2016-04-21 15:19:32 +03:00
|
|
|
chdir (c_bundle_path);
|
|
|
|
|
|
|
|
setenv ("DYLD_BIND_AT_LAUNCH", "1", 1);
|
|
|
|
|
2016-02-15 20:24:22 +03:00
|
|
|
#if TARGET_OS_WATCH
|
|
|
|
// watchOS can raise signals just fine...
|
|
|
|
// we might want to move this inside mono at some point.
|
|
|
|
signal (SIGPIPE, SIG_IGN);
|
|
|
|
#endif
|
2016-04-21 15:19:32 +03:00
|
|
|
|
2021-03-18 09:23:39 +03:00
|
|
|
xamarin_bridge_setup ();
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("Spin-up time");
|
|
|
|
|
|
|
|
{
|
|
|
|
/*
|
2021-05-27 17:42:09 +03:00
|
|
|
* Command line arguments for mobile targets (iOS / tvOS / watchOS):
|
2016-04-21 15:19:32 +03:00
|
|
|
* -debugtrack: [Simulator only]
|
|
|
|
* If we should track zombie NSObjects and aggressively poke the GC to collect
|
|
|
|
* every second.
|
|
|
|
* -monodevelop-port=<port>
|
|
|
|
* The port MonoDevelop is listening on (or we should listen on).
|
|
|
|
* Overrides whatever any configuration file says.
|
|
|
|
* -debug:
|
|
|
|
* Enables debugging (it is enabled by default, but maybe one day in the future
|
|
|
|
* we can disable it by default so that when the user clicks on the app on the
|
|
|
|
* device while *not* debugging he doesn't have to wait 2 extra seconds for it
|
|
|
|
* to start up).
|
|
|
|
* -connection-mode=[wifi|usb|none]:
|
|
|
|
* Select how to connect (or not) to MonoDevelop. No need to rebuild the
|
|
|
|
* app anymore when switching between wifi and usb debugging since this
|
|
|
|
* option overrides whatever the configuration files says. Setting 'none'
|
|
|
|
* when not debugging or profiling saves 2s on startup (since the app
|
|
|
|
* won't try to connect to MonoDevelop). If not set the current default is
|
|
|
|
* to check the configuration files (some time in the future this will be
|
|
|
|
* changed, so that it defaults to 'none'. This way there will be no
|
|
|
|
* 2s delay on startup when running it manually by clicking on the icon).
|
|
|
|
* -app-arg=<argument>:
|
|
|
|
* <argument> will be passed to the app as a command line argument. Can be
|
|
|
|
* specified multiple times.
|
|
|
|
* -setenv=<key>=<value>
|
|
|
|
* Set the environment variable <key> to the value <value>
|
2021-05-27 17:42:09 +03:00
|
|
|
*
|
|
|
|
* For desktop targets (macOS / Mac Catalyst) we pass all the command
|
|
|
|
* line arguments directly to the managed Main method.
|
|
|
|
*
|
2016-04-21 15:19:32 +03:00
|
|
|
*/
|
|
|
|
int i = 0;
|
|
|
|
for (i = 0; i < argc; i++) {
|
2021-05-27 17:42:09 +03:00
|
|
|
#if TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
|
|
|
managed_argv [managed_argc++] = argv [i];
|
|
|
|
#else
|
2016-04-21 15:19:32 +03:00
|
|
|
char *arg = argv [i];
|
|
|
|
char *name;
|
|
|
|
char *value;
|
|
|
|
|
|
|
|
if (arg [0] == '-') {
|
|
|
|
arg++;
|
|
|
|
if (arg [0] == '-')
|
|
|
|
arg++;
|
|
|
|
} else if (arg [0] == '/') {
|
|
|
|
arg++;
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
value = arg;
|
|
|
|
name = NULL;
|
|
|
|
|
|
|
|
while (*++value) {
|
|
|
|
if (*value == '=' || *value == ':') {
|
2019-11-18 16:36:47 +03:00
|
|
|
name = strndup (arg, (size_t) (value - arg));
|
2016-04-21 15:19:32 +03:00
|
|
|
value++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
name = strdup (arg);
|
|
|
|
|
|
|
|
if (*value == 0)
|
|
|
|
value = NULL;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (!strcmp (name, "debugtrack")) {
|
|
|
|
xamarin_gc_pump = true;
|
|
|
|
} else if (!strcmp (name, "monodevelop-port")) {
|
|
|
|
if (!value && argc > i + 1)
|
|
|
|
value = argv [++i];
|
|
|
|
if (value) {
|
2019-12-12 06:17:29 +03:00
|
|
|
monotouch_set_monodevelop_port ((int) strtol (value, NULL, 10));
|
2016-04-21 15:19:32 +03:00
|
|
|
} else {
|
2016-09-06 23:55:23 +03:00
|
|
|
PRINT ("MonoTouch: --%s requires an argument.", name);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
} else if (!strcmp (name, "connection-mode")) {
|
|
|
|
if (!value && argc > i + 1)
|
|
|
|
value = argv [++i];
|
|
|
|
if (value) {
|
|
|
|
monotouch_set_connection_mode (value);
|
|
|
|
} else {
|
2016-09-06 23:55:23 +03:00
|
|
|
PRINT ("MonoTouch: --%s requires an argument.", name);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
if (!strcmp (name, "app-arg")) {
|
|
|
|
if (!value && argc > i + 1)
|
|
|
|
value = argv [++i];
|
|
|
|
if (value) {
|
|
|
|
managed_argv [managed_argc++] = value;
|
|
|
|
} else {
|
2016-09-06 23:55:23 +03:00
|
|
|
PRINT ("MonoTouch: --%s requires an argument.", name);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
} else if (!strcmp (name, "setenv")) {
|
|
|
|
if (!value && argc > i + 1)
|
|
|
|
value = argv [++i];
|
|
|
|
if (value) {
|
|
|
|
char *k = strdup (value);
|
|
|
|
char *v = strchr (k, '=');
|
|
|
|
if (v) {
|
|
|
|
*v = 0;
|
|
|
|
v++;
|
|
|
|
LOG ("MonoTouch: Setting %s=%s", k, v);
|
2019-11-26 16:30:05 +03:00
|
|
|
// arguments comes from mtouch (and developer), i.e. a trusted source
|
2016-04-21 15:19:32 +03:00
|
|
|
setenv (k, v, 1);
|
|
|
|
}
|
|
|
|
free (k);
|
|
|
|
} else {
|
2016-09-06 23:55:23 +03:00
|
|
|
PRINT ("MonoTouch: --%s requires an argument.", name);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free (name);
|
2021-05-27 17:42:09 +03:00
|
|
|
#endif // TARGET_OS_OSX || TARGET_OS_MACCATALYST
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2018-11-21 19:48:15 +03:00
|
|
|
xamarin_initialize_cocoa_threads (monotouch_configure_debugging);
|
2016-04-21 15:19:32 +03:00
|
|
|
#else
|
2018-11-21 19:48:15 +03:00
|
|
|
xamarin_initialize_cocoa_threads (NULL);
|
2016-04-21 15:19:32 +03:00
|
|
|
#endif
|
|
|
|
|
2021-03-22 10:04:56 +03:00
|
|
|
#if DOTNET
|
|
|
|
xamarin_vm_initialize ();
|
|
|
|
#endif
|
2021-03-29 23:23:38 +03:00
|
|
|
xamarin_bridge_initialize ();
|
2021-03-22 10:04:56 +03:00
|
|
|
|
2016-04-21 15:19:32 +03:00
|
|
|
xamarin_initialize ();
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("\tmonotouch init time");
|
|
|
|
|
2021-06-28 18:12:37 +03:00
|
|
|
if (xamarin_register_assemblies != NULL)
|
|
|
|
xamarin_register_assemblies ();
|
|
|
|
|
2016-04-21 15:19:32 +03:00
|
|
|
if (xamarin_executable_name) {
|
2016-06-02 13:18:45 +03:00
|
|
|
assembly = xamarin_open_and_register (xamarin_executable_name, &exception_gchandle);
|
2021-02-11 10:18:38 +03:00
|
|
|
if (exception_gchandle != NULL)
|
2016-06-02 13:18:45 +03:00
|
|
|
xamarin_process_managed_exception_gchandle (exception_gchandle);
|
2016-04-21 15:19:32 +03:00
|
|
|
} else {
|
|
|
|
const char *last_slash = strrchr (argv [0], '/');
|
|
|
|
const char *basename = last_slash ? last_slash + 1 : argv [0];
|
|
|
|
char *aname = xamarin_strdup_printf ("%s.exe", basename);
|
|
|
|
|
2016-06-02 13:18:45 +03:00
|
|
|
assembly = xamarin_open_and_register (aname, &exception_gchandle);
|
2016-04-21 15:19:32 +03:00
|
|
|
xamarin_free (aname);
|
2016-06-02 13:18:45 +03:00
|
|
|
|
2021-02-11 10:18:38 +03:00
|
|
|
if (exception_gchandle != NULL)
|
2016-06-02 13:18:45 +03:00
|
|
|
xamarin_process_managed_exception_gchandle (exception_gchandle);
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
|
|
|
|
2018-02-12 18:59:39 +03:00
|
|
|
if (xamarin_supports_dynamic_registration) {
|
2021-04-21 16:00:10 +03:00
|
|
|
MonoReflectionAssembly *rassembly = mono_assembly_get_object (mono_domain_get (), assembly);
|
|
|
|
xamarin_register_entry_assembly (rassembly, &exception_gchandle);
|
|
|
|
xamarin_mono_object_release (&rassembly);
|
2021-02-11 10:18:38 +03:00
|
|
|
if (exception_gchandle != NULL)
|
2018-02-12 18:59:39 +03:00
|
|
|
xamarin_process_managed_exception_gchandle (exception_gchandle);
|
|
|
|
}
|
2016-04-21 15:19:32 +03:00
|
|
|
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("\tAssembly register time");
|
|
|
|
|
|
|
|
[[[XamarinGCSupport alloc] init] autorelease];
|
|
|
|
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("\tGC defer time");
|
|
|
|
|
|
|
|
DEBUG_LAUNCH_TIME_PRINT ("Total initialization time");
|
|
|
|
|
2016-02-15 21:02:14 +03:00
|
|
|
int rv = 0;
|
2017-04-10 07:48:35 +03:00
|
|
|
switch (launch_mode) {
|
|
|
|
case XamarinLaunchModeExtension:
|
2016-07-26 18:39:33 +03:00
|
|
|
char base_dir [1024];
|
|
|
|
char config_file_name [1024];
|
|
|
|
|
|
|
|
snprintf (base_dir, sizeof (base_dir), "%s/" ARCH_SUBDIR, xamarin_get_bundle_path ());
|
|
|
|
snprintf (config_file_name, sizeof (config_file_name), "%s/%s.config", base_dir, xamarin_executable_name); // xamarin_executable_name should never be NULL for extensions.
|
|
|
|
|
2021-05-20 08:33:26 +03:00
|
|
|
#if defined (CORECLR_RUNTIME)
|
|
|
|
// Need to figure out how to implement the equivalent of mono_domain_set_config for CoreCLR.
|
|
|
|
// That will need a test case (app extension), which we haven't implemented for CoreCLR yet.
|
|
|
|
// It's likely to require a completely different implementation, probably a property passed to coreclr_initialize.
|
|
|
|
xamarin_assertion_message ("Not implemented for CoreCLR: mono_domain_set_config.");
|
|
|
|
#else
|
2016-07-26 18:39:33 +03:00
|
|
|
mono_domain_set_config (mono_domain_get (), base_dir, config_file_name);
|
2021-05-20 08:33:26 +03:00
|
|
|
#endif
|
2016-07-26 18:39:33 +03:00
|
|
|
|
2016-02-15 21:02:14 +03:00
|
|
|
rv = xamarin_extension_main (argc, argv);
|
2017-04-10 07:48:35 +03:00
|
|
|
break;
|
|
|
|
case XamarinLaunchModeApp:
|
2017-05-31 20:04:55 +03:00
|
|
|
rv = mono_jit_exec (mono_domain_get (), assembly, managed_argc, managed_argv);
|
2017-04-10 07:48:35 +03:00
|
|
|
break;
|
|
|
|
case XamarinLaunchModeEmbedded:
|
|
|
|
// do nothing
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
xamarin_assertion_message ("Invalid launch mode: %i.", launch_mode);
|
|
|
|
break;
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|
2021-03-22 14:53:52 +03:00
|
|
|
|
|
|
|
xamarin_mono_object_release (&assembly);
|
2016-04-21 15:19:32 +03:00
|
|
|
|
[runtime] Release the block_wrapper_queue and xamarin_wrapper_hash dictionaries upon process exit. (#11751)
While not strictly necessary to not leak (because the process is exiting
anyway), it makes it easier to read leak reports, because these dictionaries
won't show up as leaked memory anymore.
Before:
There were 258096 MonoObjects created, 258015 MonoObjects freed, so 81 were not freed. (dynamic registrar)
There were 205834 MonoObjects created, 205833 MonoObjects freed, so 1 were not freed. (static registrar)
After:
There were 258104 MonoObjects created, 258025 MonoObjects freed, so 79 were not freed. (dynamic registrar)
There were 205834 MonoObjects created, 205834 MonoObjects freed, so no leaked MonoObjects. (static registrar)
2021-06-01 08:35:29 +03:00
|
|
|
xamarin_release_static_dictionaries ();
|
|
|
|
|
2021-05-25 09:19:27 +03:00
|
|
|
xamarin_bridge_shutdown ();
|
|
|
|
|
2016-02-15 21:02:14 +03:00
|
|
|
return rv;
|
2016-04-21 15:19:32 +03:00
|
|
|
}
|