123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603 |
- /**
- * \file
- * AppDomain functions
- *
- * Authors:
- * Dietmar Maurer (dietmar@ximian.com)
- * Patrik Torstensson
- * Gonzalo Paniagua Javier (gonzalo@ximian.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2012 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
- #include <config.h>
- #include <glib.h>
- #include <string.h>
- #include <errno.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_UTIME_H
- #include <utime.h>
- #else
- #ifdef HAVE_SYS_UTIME_H
- #include <sys/utime.h>
- #endif
- #endif
- #include <mono/metadata/gc-internals.h>
- #include <mono/metadata/object.h>
- #include <mono/metadata/appdomain-icalls.h>
- #include <mono/metadata/class-init.h>
- #include <mono/metadata/domain-internals.h>
- #include "mono/metadata/metadata-internals.h"
- #include <mono/metadata/assembly-internals.h>
- #include <mono/metadata/exception.h>
- #include <mono/metadata/exception-internals.h>
- #include <mono/metadata/threads.h>
- #include <mono/metadata/threadpool.h>
- #include <mono/metadata/tabledefs.h>
- #include <mono/metadata/mono-gc.h>
- #include <mono/metadata/mono-hash-internals.h>
- #include <mono/metadata/marshal.h>
- #include <mono/metadata/marshal-internals.h>
- #include <mono/metadata/monitor.h>
- #include <mono/metadata/mono-debug.h>
- #include <mono/metadata/attach.h>
- #include <mono/metadata/w32file.h>
- #include <mono/metadata/lock-tracer.h>
- #include <mono/metadata/console-io.h>
- #include <mono/metadata/threads-types.h>
- #include <mono/metadata/tokentype.h>
- #include <mono/metadata/profiler-private.h>
- #include <mono/metadata/reflection-internals.h>
- #include <mono/metadata/abi-details.h>
- #include <mono/metadata/w32socket.h>
- #include <mono/utils/mono-uri.h>
- #include <mono/utils/mono-logger-internals.h>
- #include <mono/utils/mono-path.h>
- #include <mono/utils/mono-stdlib.h>
- #include <mono/utils/mono-io-portability.h>
- #include <mono/utils/mono-error-internals.h>
- #include <mono/utils/atomic.h>
- #include <mono/utils/mono-memory-model.h>
- #include <mono/utils/mono-threads.h>
- #include <mono/metadata/w32handle.h>
- #include <mono/metadata/w32error.h>
- #include <mono/utils/w32api.h>
- #ifdef ENABLE_PERFTRACING
- #include <eventpipe/ds-server.h>
- #endif
- #ifdef HOST_WIN32
- #include <direct.h>
- #endif
- #include "object-internals.h"
- #include "icall-decl.h"
- typedef struct
- {
- int runtime_count;
- int assemblybinding_count;
- MonoDomain *domain;
- gchar *filename;
- } RuntimeConfig;
- #ifndef ENABLE_NETCORE
- static gunichar2 process_guid [36];
- static gboolean process_guid_set = FALSE;
- #endif
- static gboolean no_exec = FALSE;
- #ifdef ENABLE_NETCORE
- static int n_appctx_props;
- static gunichar2 **appctx_keys;
- static gunichar2 **appctx_values;
- #endif
- static const char *
- mono_check_corlib_version_internal (void);
- static MonoAssembly *
- mono_domain_assembly_preload (MonoAssemblyLoadContext *alc,
- MonoAssemblyName *aname,
- gchar **assemblies_path,
- gboolean refonly,
- gpointer user_data,
- MonoError *error);
- static MonoAssembly *
- mono_domain_assembly_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting,
- MonoAssemblyName *aname,
- gboolean refonly,
- gboolean postload,
- gpointer user_data,
- MonoError *error);
- static gboolean ignore_version_and_key_when_finding_assemblies_already_loaded = FALSE;
- void
- mono_set_ignore_version_and_key_when_finding_assemblies_already_loaded(gboolean value)
- {
- ignore_version_and_key_when_finding_assemblies_already_loaded = value;
- }
- static void
- mono_domain_fire_assembly_load (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer user_data, MonoError *error_out);
- static gboolean
- mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx);
- static void
- add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht);
- #if ENABLE_NETCORE
- static void
- add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass);
- #endif
- #ifndef ENABLE_NETCORE
- static MonoAppDomainHandle
- mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error);
- static MonoDomain *
- mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error);
- #endif
- static void
- mono_context_set_default_context (MonoDomain *domain);
- static char *
- get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error);
- static MonoLoadFunc load_function = NULL;
- /* Lazy class loading functions */
- static GENERATE_GET_CLASS_WITH_CACHE (assembly, "System.Reflection", "Assembly");
- #ifdef ENABLE_NETCORE
- static GENERATE_GET_CLASS_WITH_CACHE (app_context, "System", "AppContext");
- #endif
- #ifndef ENABLE_NETCORE
- GENERATE_GET_CLASS_WITH_CACHE (appdomain, MONO_APPDOMAIN_CLASS_NAME_SPACE, MONO_APPDOMAIN_CLASS_NAME);
- GENERATE_GET_CLASS_WITH_CACHE (appdomain_setup, MONO_APPDOMAIN_SETUP_CLASS_NAME_SPACE, MONO_APPDOMAIN_SETUP_CLASS_NAME);
- #else
- MonoClass*
- mono_class_get_appdomain_class (void)
- {
- return mono_defaults.object_class;
- }
- #endif
- static MonoDomain *
- mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain);
- static void
- mono_error_set_appdomain_unloaded (MonoError *error)
- {
- mono_error_set_generic_error (error, "System", "AppDomainUnloadedException", "");
- }
- void
- mono_install_runtime_load (MonoLoadFunc func)
- {
- load_function = func;
- }
- MonoDomain*
- mono_runtime_load (const char *filename, const char *runtime_version)
- {
- g_assert (load_function);
- return load_function (filename, runtime_version);
- }
- /**
- * mono_runtime_set_no_exec:
- *
- * Instructs the runtime to operate in static mode, i.e. avoid/do not
- * allow managed code execution. This is useful for running the AOT
- * compiler on platforms which allow full-aot execution only. This
- * should be called before mono_runtime_init ().
- */
- void
- mono_runtime_set_no_exec (gboolean val)
- {
- no_exec = val;
- }
- /**
- * mono_runtime_get_no_exec:
- *
- * If true, then the runtime will not allow managed code execution.
- */
- gboolean
- mono_runtime_get_no_exec (void)
- {
- return no_exec;
- }
- static void
- create_domain_objects (MonoDomain *domain)
- {
- HANDLE_FUNCTION_ENTER ();
- ERROR_DECL (error);
- MonoDomain *old_domain = mono_domain_get ();
- MonoStringHandle arg;
- MonoVTable *string_vt;
- MonoClassField *string_empty_fld;
- if (domain != old_domain) {
- mono_thread_push_appdomain_ref (domain);
- mono_domain_set_internal_with_options (domain, FALSE);
- }
- /*
- * Initialize String.Empty. This enables the removal of
- * the static cctor of the String class.
- */
- string_vt = mono_class_vtable_checked (domain, mono_defaults.string_class, error);
- mono_error_assert_ok (error);
- string_empty_fld = mono_class_get_field_from_name_full (mono_defaults.string_class, "Empty", NULL);
- g_assert (string_empty_fld);
- MonoStringHandle empty_str = mono_string_new_handle (domain, "", error);
- mono_error_assert_ok (error);
- empty_str = mono_string_intern_checked (empty_str, error);
- mono_error_assert_ok (error);
- mono_field_static_set_value_internal (string_vt, string_empty_fld, MONO_HANDLE_RAW (empty_str));
- domain->empty_string = MONO_HANDLE_RAW (empty_str);
- mono_gc_wbarrier_generic_nostore_internal (&domain->empty_string);
- /*
- * Create an instance early since we can't do it when there is no memory.
- */
- arg = mono_string_new_handle (domain, "Out of memory", error);
- mono_error_assert_ok (error);
- domain->out_of_memory_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "OutOfMemoryException", arg, NULL_HANDLE_STRING, error));
- mono_gc_wbarrier_generic_nostore_internal (&domain->out_of_memory_ex);
- mono_error_assert_ok (error);
- /*
- * These two are needed because the signal handlers might be executing on
- * an alternate stack, and Boehm GC can't handle that.
- */
- arg = mono_string_new_handle (domain, "A null value was found where an object instance was required", error);
- mono_error_assert_ok (error);
- domain->null_reference_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "NullReferenceException", arg, NULL_HANDLE_STRING, error));
- mono_gc_wbarrier_generic_nostore_internal (&domain->null_reference_ex);
- mono_error_assert_ok (error);
- arg = mono_string_new_handle (domain, "The requested operation caused a stack overflow.", error);
- mono_error_assert_ok (error);
- domain->stack_overflow_ex = MONO_HANDLE_RAW (mono_exception_from_name_two_strings_checked (mono_defaults.corlib, "System", "StackOverflowException", arg, NULL_HANDLE_STRING, error));
- mono_gc_wbarrier_generic_nostore_internal (&domain->stack_overflow_ex);
- mono_error_assert_ok (error);
- /*The ephemeron tombstone i*/
- domain->ephemeron_tombstone = MONO_HANDLE_RAW (mono_object_new_handle (domain, mono_defaults.object_class, error));
- mono_gc_wbarrier_generic_nostore_internal (&domain->ephemeron_tombstone);
- mono_error_assert_ok (error);
- if (domain != old_domain) {
- mono_thread_pop_appdomain_ref ();
- mono_domain_set_internal_with_options (old_domain, FALSE);
- }
- /*
- * This class is used during exception handling, so initialize it here, to prevent
- * stack overflows while handling stack overflows.
- */
- mono_class_init_internal (mono_class_create_array (mono_defaults.int_class, 1));
- HANDLE_FUNCTION_RETURN ();
- }
- /**
- * mono_runtime_init:
- * \param domain domain returned by \c mono_init
- *
- * Initialize the core AppDomain: this function will run also some
- * IL initialization code, so it needs the execution engine to be fully
- * operational.
- *
- * \c AppDomain.SetupInformation is set up in \c mono_runtime_exec_main, where
- * we know the \c entry_assembly.
- *
- */
- void
- mono_runtime_init (MonoDomain *domain, MonoThreadStartCB start_cb, MonoThreadAttachCB attach_cb)
- {
- ERROR_DECL (error);
- mono_runtime_init_checked (domain, start_cb, attach_cb, error);
- mono_error_cleanup (error);
- }
- void
- mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoThreadAttachCB attach_cb, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoAppDomainHandle ad;
- error_init (error);
- mono_portability_helpers_init ();
-
- mono_gc_base_init ();
- mono_monitor_init ();
- mono_marshal_init ();
- mono_gc_init_icalls ();
- // We have to append here because otherwise this will run before the netcore hook (which is installed first), see https://github.com/dotnet/runtime/issues/34273
- mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload, GUINT_TO_POINTER (FALSE), FALSE, TRUE);
- mono_install_assembly_search_hook_v2 (mono_domain_assembly_search, GUINT_TO_POINTER (FALSE), FALSE, FALSE, FALSE);
- mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search, GUINT_TO_POINTER (FALSE), FALSE, TRUE, FALSE);
- mono_install_assembly_load_hook_v2 (mono_domain_fire_assembly_load, NULL, FALSE);
- #ifndef ENABLE_NETCORE // refonly hooks
- mono_install_assembly_preload_hook_v2 (mono_domain_assembly_preload, GUINT_TO_POINTER (TRUE), TRUE, FALSE);
- mono_install_assembly_search_hook_v2 (mono_domain_assembly_search, GUINT_TO_POINTER (TRUE), TRUE, FALSE, FALSE);
- mono_install_assembly_search_hook_v2 (mono_domain_assembly_postload_search, GUINT_TO_POINTER (TRUE), TRUE, TRUE, FALSE);
- mono_install_assembly_asmctx_from_path_hook (mono_domain_asmctx_from_path, NULL);
- #endif
- mono_thread_init (start_cb, attach_cb);
- if (!mono_runtime_get_no_exec ()) {
- MonoClass *klass;
- #ifndef ENABLE_NETCORE
- klass = mono_class_get_appdomain_setup_class ();
- MonoAppDomainSetupHandle setup;
- setup = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_pinned_handle (domain, klass, error));
- goto_if_nok (error, exit);
- #endif
- klass = mono_class_get_appdomain_class ();
- ad = MONO_HANDLE_CAST (MonoAppDomain, mono_object_new_pinned_handle (domain, klass, error));
- goto_if_nok (error, exit);
- #ifndef ENABLE_NETCORE
- MONO_HANDLE_SETVAL (ad, data, MonoDomain*, domain);
- #endif
- domain->domain = MONO_HANDLE_RAW (ad);
- #ifndef ENABLE_NETCORE
- mono_gc_wbarrier_generic_nostore_internal (&domain->domain);
- domain->setup = MONO_HANDLE_RAW (setup);
- mono_gc_wbarrier_generic_nostore_internal (&domain->setup);
- #endif
- }
- mono_thread_internal_attach (domain);
- #if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
- ds_server_init ();
- ds_server_pause_for_diagnostics_monitor ();
- #endif
- mono_type_initialization_init ();
- if (!mono_runtime_get_no_exec ())
- create_domain_objects (domain);
- /* GC init has to happen after thread init */
- mono_gc_init ();
- /* contexts use GC handles, so they must be initialized after the GC */
- #ifndef ENABLE_NETCORE
- mono_context_init_checked (domain, error);
- goto_if_nok (error, exit);
- mono_context_set_default_context (domain);
- #endif
- #ifdef ENABLE_NETCORE
- if (!mono_runtime_get_no_exec ())
- mono_runtime_install_appctx_properties ();
- #endif
- mono_network_init ();
- mono_console_init ();
- mono_attach_init ();
- mono_locks_tracer_init ();
- /* mscorlib is loaded before we install the load hook */
- mono_domain_fire_assembly_load (mono_domain_default_alc (domain), mono_defaults.corlib->assembly, NULL, error);
- goto_if_nok (error, exit);
- exit:
- HANDLE_FUNCTION_RETURN ();
- }
- static void
- mono_context_set_default_context (MonoDomain *domain)
- {
- if (mono_runtime_get_no_exec ())
- return;
- HANDLE_FUNCTION_ENTER ();
- mono_context_set_handle (MONO_HANDLE_NEW (MonoAppContext, domain->default_context));
- HANDLE_FUNCTION_RETURN ();
- }
- static char*
- mono_get_corlib_version (void)
- {
- ERROR_DECL (error);
- MonoClass *klass;
- MonoClassField *field;
- klass = mono_class_load_from_name (mono_defaults.corlib, "System", "Environment");
- mono_class_init_internal (klass);
- field = mono_class_get_field_from_name_full (klass, "mono_corlib_version", NULL);
- if (!field)
- return NULL;
- if (! (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_LITERAL)))
- return NULL;
- char *value;
- MonoTypeEnum field_type;
- const char *data = mono_class_get_field_default_value (field, &field_type);
- if (field_type != MONO_TYPE_STRING)
- return NULL;
- mono_metadata_read_constant_value (data, field_type, &value, error);
- mono_error_assert_ok (error);
- char *res = mono_string_from_blob (value, error);
- mono_error_assert_ok (error);
- return res;
- }
- /**
- * mono_check_corlib_version:
- * Checks that the corlib that is loaded matches the version of this runtime.
- * \returns NULL if the runtime will work with the corlib, or a \c g_malloc
- * allocated string with the error otherwise.
- */
- const char*
- mono_check_corlib_version (void)
- {
- const char* res;
- MONO_ENTER_GC_UNSAFE;
- res = mono_check_corlib_version_internal ();
- MONO_EXIT_GC_UNSAFE;
- return res;
- }
- static const char *
- mono_check_corlib_version_internal (void)
- {
- #if defined(MONO_CROSS_COMPILE)
- /* Can't read the corlib version because we only have the target class layouts */
- return NULL;
- #else
- char *result = NULL;
- char *version = mono_get_corlib_version ();
- if (!version) {
- result = g_strdup_printf ("expected corlib string (%s) but not found or not string", MONO_CORLIB_VERSION);
- goto exit;
- }
- if (strcmp (version, MONO_CORLIB_VERSION) != 0) {
- result = g_strdup_printf ("The runtime did not find the mscorlib.dll it expected. "
- "Expected interface version %s but found %s. Check that "
- "your runtime and class libraries are matching.",
- MONO_CORLIB_VERSION, version);
- goto exit;
- }
- /* Check that the managed and unmanaged layout of MonoInternalThread matches */
- guint32 native_offset;
- guint32 managed_offset;
- native_offset = (guint32) MONO_STRUCT_OFFSET (MonoInternalThread, last);
- managed_offset = mono_field_get_offset (mono_class_get_field_from_name_full (mono_defaults.internal_thread_class, "last", NULL));
- if (native_offset != managed_offset)
- result = g_strdup_printf ("expected InternalThread.last field offset %u, found %u. See InternalThread.last comment", native_offset, managed_offset);
- exit:
- g_free (version);
- return result;
- #endif
- }
- /**
- * mono_context_init:
- * \param domain The domain where the \c System.Runtime.Remoting.Context.Context is initialized
- * Initializes the \p domain's default \c System.Runtime.Remoting 's Context.
- */
- void
- mono_context_init (MonoDomain *domain)
- {
- ERROR_DECL (error);
- mono_context_init_checked (domain, error);
- mono_error_cleanup (error);
- }
- void
- mono_context_init_checked (MonoDomain *domain, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoClass *klass;
- MonoAppContextHandle context;
- error_init (error);
- if (mono_runtime_get_no_exec ())
- goto exit;
- klass = mono_class_load_from_name (mono_defaults.corlib, "System.Runtime.Remoting.Contexts", "Context");
- context = MONO_HANDLE_CAST (MonoAppContext, mono_object_new_pinned_handle (domain, klass, error));
- goto_if_nok (error, exit);
- MONO_HANDLE_SETVAL (context, domain_id, gint32, domain->domain_id);
- MONO_HANDLE_SETVAL (context, context_id, gint32, 0);
- mono_threads_register_app_context (context, error);
- mono_error_assert_ok (error);
- domain->default_context = MONO_HANDLE_RAW (context);
- exit:
- HANDLE_FUNCTION_RETURN ();
- }
- /**
- * mono_runtime_cleanup:
- * \param domain unused.
- *
- * Internal routine.
- *
- * This must not be called while there are still running threads executing
- * managed code.
- */
- void
- mono_runtime_cleanup (MonoDomain *domain)
- {
- mono_attach_cleanup ();
- /* This ends up calling any pending pending (for at most 2 seconds) */
- mono_gc_cleanup ();
- mono_thread_cleanup ();
- mono_network_cleanup ();
- mono_marshal_cleanup ();
- mono_type_initialization_cleanup ();
- mono_monitor_cleanup ();
- }
- static MonoDomainFunc quit_function = NULL;
- /**
- * mono_install_runtime_cleanup:
- */
- void
- mono_install_runtime_cleanup (MonoDomainFunc func)
- {
- quit_function = func;
- }
- /**
- * mono_runtime_quit:
- */
- void
- mono_runtime_quit (void)
- {
- MONO_STACKDATA (dummy);
- (void) mono_threads_enter_gc_unsafe_region_unbalanced_internal (&dummy);
- // after quit_function (in particular, mini_cleanup) everything is
- // cleaned up so MONO_EXIT_GC_UNSAFE can't work and doesn't make sense.
-
- mono_runtime_quit_internal ();
- }
- /**
- * mono_runtime_quit_internal:
- */
- void
- mono_runtime_quit_internal (void)
- {
- MONO_REQ_GC_UNSAFE_MODE;
- // but note that when we return, we're not in GC Unsafe mode anymore.
- // After clean up threads don't _have_ a thread state anymore.
-
- if (quit_function != NULL)
- quit_function (mono_get_root_domain (), NULL);
- }
- #ifndef ENABLE_NETCORE
- /**
- * mono_domain_create_appdomain:
- * \param friendly_name The friendly name of the appdomain to create
- * \param configuration_file The configuration file to initialize the appdomain with
- * \returns a \c MonoDomain initialized with the appdomain
- */
- MonoDomain *
- mono_domain_create_appdomain (char *friendly_name, char *configuration_file)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoDomain *domain;
- MONO_ENTER_GC_UNSAFE;
- ERROR_DECL (error);
- domain = mono_domain_create_appdomain_checked (friendly_name, configuration_file, error);
- mono_error_cleanup (error);
- MONO_EXIT_GC_UNSAFE;
- HANDLE_FUNCTION_RETURN_VAL (domain);
- }
- /**
- * mono_domain_create_appdomain_checked:
- * \param friendly_name The friendly name of the appdomain to create
- * \param configuration_file The configuration file to initialize the appdomain with
- * \param error Set on error.
- *
- * \returns a MonoDomain initialized with the appdomain. On failure sets \p error and returns NULL.
- */
- MonoDomain *
- mono_domain_create_appdomain_checked (char *friendly_name, char *configuration_file, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoDomain *result = NULL;
- #ifndef ENABLE_NETCORE
- MonoClass *klass = mono_class_get_appdomain_setup_class ();
- MonoAppDomainSetupHandle setup = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_handle (mono_domain_get (), klass, error));
- goto_if_nok (error, leave);
- MonoStringHandle config_file;
- if (configuration_file != NULL) {
- config_file = mono_string_new_handle (mono_domain_get (), configuration_file, error);
- goto_if_nok (error, leave);
- } else {
- config_file = MONO_HANDLE_NEW (MonoString, NULL);
- }
- MONO_HANDLE_SET (setup, configuration_file, config_file);
- #endif
- MonoAppDomainHandle ad;
- #ifndef ENABLE_NETCORE
- ad = mono_domain_create_appdomain_internal (friendly_name, setup, error);
- #else
- ad = MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE);
- #endif
- goto_if_nok (error, leave);
- result = mono_domain_from_appdomain_handle (ad);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (result);
- }
- #endif
- /**
- * mono_domain_set_config:
- * \param domain \c MonoDomain initialized with the appdomain we want to change
- * \param base_dir new base directory for the appdomain
- * \param config_file_name path to the new configuration for the app domain
- *
- * Used to set the system configuration for an appdomain
- *
- * Without using this, embedded builds will get 'System.Configuration.ConfigurationErrorsException:
- * Error Initializing the configuration system. ---> System.ArgumentException:
- * The 'ExeConfigFilename' argument cannot be null.' for some managed calls.
- */
- void
- mono_domain_set_config (MonoDomain *domain, const char *base_dir, const char *config_file_name)
- {
- #ifndef ENABLE_NETCORE
- HANDLE_FUNCTION_ENTER ();
- MONO_ENTER_GC_UNSAFE;
- ERROR_DECL (error);
- mono_domain_set_config_checked (domain, base_dir, config_file_name, error);
- mono_error_cleanup (error);
- MONO_EXIT_GC_UNSAFE;
- HANDLE_FUNCTION_RETURN ();
- #else
- g_assert_not_reached ();
- #endif
- }
- #ifndef ENABLE_NETCORE
- gboolean
- mono_domain_set_config_checked (MonoDomain *domain, const char *base_dir, const char *config_file_name, MonoError *error)
- {
- error_init (error);
- MonoAppDomainSetupHandle setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
- MonoStringHandle base_dir_str = mono_string_new_handle (domain, base_dir, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_SET (setup, application_base, base_dir_str);
- MonoStringHandle config_file_name_str;
- config_file_name_str = mono_string_new_handle (domain, config_file_name, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_SET (setup, configuration_file, config_file_name_str);
- leave:
- return is_ok (error);
- }
- #endif
- #ifndef ENABLE_NETCORE
- static MonoAppDomainSetupHandle
- copy_app_domain_setup (MonoDomain *domain, MonoAppDomainSetupHandle setup, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoDomain *caller_domain;
- MonoClass *ads_class;
- MonoAppDomainSetupHandle result = MONO_HANDLE_NEW (MonoAppDomainSetup, NULL);
- error_init (error);
- caller_domain = mono_domain_get ();
- ads_class = mono_class_get_appdomain_setup_class ();
- MonoAppDomainSetupHandle copy = MONO_HANDLE_CAST (MonoAppDomainSetup, mono_object_new_handle(domain, ads_class, error));
- goto_if_nok (error, leave);
- mono_domain_set_internal_with_options (domain, TRUE);
- #define XCOPY_FIELD(type, dst, field, src, error) \
- do { \
- TYPED_HANDLE_NAME (type) src_val = MONO_HANDLE_NEW_GET (type, (src), field); \
- TYPED_HANDLE_NAME (type) copied_val = MONO_HANDLE_CAST (type, mono_marshal_xdomain_copy_value_handle (MONO_HANDLE_CAST (MonoObject, src_val), error)); \
- goto_if_nok (error, leave); \
- MONO_HANDLE_SET ((dst),field,copied_val); \
- } while (0)
- #define COPY_VAL(dst,field,type,src) \
- do { \
- MONO_HANDLE_SETVAL ((dst), field, type, MONO_HANDLE_GETVAL ((src),field)); \
- } while (0)
- XCOPY_FIELD (MonoString, copy, application_base, setup, error);
- XCOPY_FIELD (MonoString, copy, application_name, setup, error);
- XCOPY_FIELD (MonoString, copy, cache_path, setup, error);
- XCOPY_FIELD (MonoString, copy, configuration_file, setup, error);
- XCOPY_FIELD (MonoString, copy, dynamic_base, setup, error);
- XCOPY_FIELD (MonoString, copy, license_file, setup, error);
- XCOPY_FIELD (MonoString, copy, private_bin_path, setup, error);
- XCOPY_FIELD (MonoString, copy, private_bin_path_probe, setup, error);
- XCOPY_FIELD (MonoString, copy, shadow_copy_directories, setup, error);
- XCOPY_FIELD (MonoString, copy, shadow_copy_files, setup, error);
- COPY_VAL (copy, publisher_policy, MonoBoolean, setup);
- COPY_VAL (copy, path_changed, MonoBoolean, setup);
- COPY_VAL (copy, loader_optimization, int, setup);
- COPY_VAL (copy, disallow_binding_redirects, MonoBoolean, setup);
- COPY_VAL (copy, disallow_code_downloads, MonoBoolean, setup);
- XCOPY_FIELD (MonoArray, copy, domain_initializer_args, setup, error);
- COPY_VAL (copy, disallow_appbase_probe, MonoBoolean, setup);
- XCOPY_FIELD (MonoObject, copy, application_trust, setup, error);
- XCOPY_FIELD (MonoArray, copy, configuration_bytes, setup, error);
- XCOPY_FIELD (MonoArray, copy, serialized_non_primitives, setup, error);
- #undef XCOPY_FIELD
- #undef COPY_VAL
-
- mono_domain_set_internal_with_options (caller_domain, TRUE);
- MONO_HANDLE_ASSIGN (result, copy);
- leave:
- HANDLE_FUNCTION_RETURN_REF (MonoAppDomainSetup, result);
- }
- #endif
- #ifndef ENABLE_NETCORE
- static MonoAppDomainHandle
- mono_domain_create_appdomain_internal (char *friendly_name, MonoAppDomainSetupHandle setup, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoAppDomainHandle result = MONO_HANDLE_NEW (MonoAppDomain, NULL);
- MonoClass *adclass;
- MonoDomain *data;
- error_init (error);
- adclass = mono_class_get_appdomain_class ();
- /* FIXME: pin all those objects */
- data = mono_domain_create();
- MonoAppDomainHandle ad = MONO_HANDLE_CAST (MonoAppDomain, mono_object_new_handle (data, adclass, error));
- goto_if_nok (error, leave);
- MONO_HANDLE_SETVAL (ad, data, MonoDomain*, data);
- data->domain = MONO_HANDLE_RAW (ad);
- mono_gc_wbarrier_generic_nostore_internal (&data->domain);
- data->friendly_name = g_strdup (friendly_name);
- MONO_PROFILER_RAISE (domain_name, (data, data->friendly_name));
- MonoStringHandle app_base;
- app_base = MONO_HANDLE_NEW_GET (MonoString, setup, application_base);
- if (MONO_HANDLE_IS_NULL (app_base)) {
- /* Inherit from the root domain since MS.NET does this */
- MonoDomain *root = mono_get_root_domain ();
- MonoAppDomainSetupHandle root_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, root->setup);
- MonoStringHandle root_app_base = MONO_HANDLE_NEW_GET (MonoString, root_setup, application_base);
- if (!MONO_HANDLE_IS_NULL (root_app_base)) {
- /* N.B. new string is in the new domain */
- MonoGCHandle gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, root_app_base), TRUE);
- MonoStringHandle s = mono_string_new_utf16_handle (data, mono_string_chars_internal (MONO_HANDLE_RAW (root_app_base)), mono_string_handle_length (root_app_base), error);
- mono_gchandle_free_internal (gchandle);
- if (!is_ok (error)) {
- g_free (data->friendly_name);
- goto leave;
- }
- MONO_HANDLE_SET (setup, application_base, s);
- }
- }
- mono_context_init_checked (data, error);
- goto_if_nok (error, leave);
- data->setup = MONO_HANDLE_RAW (copy_app_domain_setup (data, setup, error));
- mono_gc_wbarrier_generic_nostore_internal (&data->setup);
- if (!is_ok (error)) {
- g_free (data->friendly_name);
- goto leave;
- }
- mono_domain_set_options_from_config (data);
- add_assemblies_to_domain (data, mono_defaults.corlib->assembly, NULL);
- #ifndef DISABLE_SHADOW_COPY
- /*FIXME, guard this for when the debugger is not running */
- char *shadow_location;
- shadow_location = get_shadow_assembly_location_base (data, error);
- if (!is_ok (error)) {
- g_free (data->friendly_name);
- goto leave;
- }
- g_free (shadow_location);
- #endif
- create_domain_objects (data);
- MONO_HANDLE_ASSIGN (result, ad);
- leave:
- HANDLE_FUNCTION_RETURN_REF (MonoAppDomain, result);
- }
- #endif
- /**
- * mono_domain_has_type_resolve:
- * \param domain application domain being looked up
- *
- * \returns TRUE if the \c AppDomain.TypeResolve field has been set.
- */
- gboolean
- mono_domain_has_type_resolve (MonoDomain *domain)
- {
- // Check whether managed code is running, and if the managed AppDomain object doesn't exist neither does the event handler
- if (!domain->domain)
- return FALSE;
- #ifdef ENABLE_NETCORE
- return TRUE;
- #else
- MonoObject *o;
- MONO_STATIC_POINTER_INIT (MonoClassField, field)
- field = mono_class_get_field_from_name_full (mono_defaults.appdomain_class, "TypeResolve", NULL);
- g_assert (field);
- MONO_STATIC_POINTER_INIT_END (MonoClassField, field)
- mono_field_get_value_internal ((MonoObject*)(domain->domain), field, &o);
- return o != NULL;
- #endif
- }
- /**
- * mono_domain_try_type_resolve:
- * \param domain application domain in which to resolve the type
- * \param name the name of the type to resolve or NULL.
- * \param typebuilder A \c System.Reflection.Emit.TypeBuilder, used if name is NULL.
- *
- * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
- * the assembly that matches name, or ((TypeBuilder)typebuilder).FullName.
- *
- * \returns A \c MonoReflectionAssembly or NULL if not found
- */
- MonoReflectionAssembly *
- mono_domain_try_type_resolve (MonoDomain *domain, char *name, MonoObject *typebuilder_raw)
- {
- HANDLE_FUNCTION_ENTER ();
- g_assert (domain);
- g_assert (name || typebuilder_raw);
- ERROR_DECL (error);
- MonoReflectionAssemblyHandle ret = NULL_HANDLE_INIT;
- // This will not work correctly on netcore
- if (name) {
- MonoStringHandle name_handle = mono_string_new_handle (mono_domain_get (), name, error);
- goto_if_nok (error, exit);
- ret = mono_domain_try_type_resolve_name (domain, NULL, name_handle, error);
- } else {
- #ifndef ENABLE_NETCORE
- MONO_HANDLE_DCL (MonoObject, typebuilder);
- ret = mono_domain_try_type_resolve_typebuilder (domain, MONO_HANDLE_CAST (MonoReflectionTypeBuilder, typebuilder), error);
- #else
- // TODO: make this work on netcore when working on SRE.TypeBuilder
- g_assert_not_reached ();
- #endif
- }
- exit:
- mono_error_cleanup (error);
- HANDLE_FUNCTION_RETURN_OBJ (ret);
- }
- #ifdef ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error)
- {
- MonoObjectHandle ret;
- MonoReflectionAssemblyHandle assembly_handle;
- HANDLE_FUNCTION_ENTER ();
- MONO_STATIC_POINTER_INIT (MonoMethod, method)
- static gboolean inited;
- // avoid repeatedly calling mono_class_get_method_from_name_checked
- if (!inited) {
- ERROR_DECL (local_error);
- MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
- g_assert (alc_class);
- method = mono_class_get_method_from_name_checked (alc_class, "OnTypeResolve", -1, 0, local_error);
- mono_error_cleanup (local_error);
- inited = TRUE;
- }
- MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
- if (!method)
- goto return_null;
- g_assert (domain);
- g_assert (MONO_HANDLE_BOOL (name));
- if (mono_runtime_get_no_exec ())
- goto return_null;
- if (assembly) {
- assembly_handle = mono_assembly_get_object_handle (domain, assembly, error);
- goto_if_nok (error, return_null);
- }
- gpointer args [2];
- args [0] = assembly ? MONO_HANDLE_RAW (assembly_handle) : NULL;
- args [1] = MONO_HANDLE_RAW (name);
- ret = mono_runtime_try_invoke_handle (method, NULL_HANDLE, args, error);
- goto_if_nok (error, return_null);
- goto exit;
- return_null:
- ret = NULL_HANDLE;
- exit:
- HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
- }
- #else
- /**
- * mono_class_get_appdomain_do_type_resolve_method:
- *
- * This routine returns System.AppDomain.DoTypeResolve.
- */
- static MonoMethod *
- mono_class_get_appdomain_do_type_resolve_method (MonoError *error)
- {
- MONO_STATIC_POINTER_INIT (MonoMethod, method)
- method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeResolve", -1, 0, error);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
- if (method == NULL)
- g_warning ("%s method AppDomain.DoTypeResolve not found. %s\n", __func__, mono_error_get_message (error));
- return method;
- }
- /**
- * mono_class_get_appdomain_do_type_builder_resolve_method:
- *
- * This routine returns System.AppDomain.DoTypeBuilderResolve.
- */
- static MonoMethod *
- mono_class_get_appdomain_do_type_builder_resolve_method (MonoError *error)
- {
- MONO_STATIC_POINTER_INIT (MonoMethod, method)
- method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoTypeBuilderResolve", -1, 0, error);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
- if (method == NULL)
- g_warning ("%s method AppDomain.DoTypeBuilderResolve not found. %s\n", __func__, mono_error_get_message (error));
- return method;
- }
- /**
- * mono_domain_try_type_resolve_name:
- * \param domain application domain in which to resolve the type
- * \param name the name of the type to resolve.
- *
- * This routine invokes the internal \c System.AppDomain.DoTypeResolve and returns
- * the assembly that matches name.
- *
- * \returns A \c MonoReflectionAssembly or NULL if not found
- */
- MonoReflectionAssemblyHandle
- mono_domain_try_type_resolve_name (MonoDomain *domain, MonoAssembly *assembly, MonoStringHandle name, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- void *params [1] = { 0 };
- g_assert (domain);
- g_assert (MONO_HANDLE_BOOL (name));
- g_assert (error);
- error_init (error);
- MonoMethod *method;
- method = mono_class_get_appdomain_do_type_resolve_method (error);
- goto_if_nok (error, return_null);
- MonoAppDomainHandle appdomain;
- appdomain = MONO_HANDLE_NEW (MonoAppDomain, domain->domain);
- MonoObjectHandle ret;
- params [0] = MONO_HANDLE_RAW (name);
- ret = mono_runtime_invoke_handle (method, MONO_HANDLE_CAST (MonoObject, appdomain), params, error);
- goto_if_nok (error, return_null);
- goto exit;
- return_null:
- ret = NULL_HANDLE;
- exit:
- HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
- }
- /**
- * mono_domain_try_type_resolve_typebuilder:
- * \param domain application domain in which to resolve the type
- * \param typebuilder A \c System.Reflection.Emit.TypeBuilder; typebuilder.FullName is the name of the type to resolve.
- *
- * This routine invokes the internal \c System.AppDomain.DoTypeBuilderResolve and returns
- * the assembly that matches typebuilder.FullName.
- *
- * \returns A \c MonoReflectionAssembly or NULL_HANDLE if not found
- */
- MonoReflectionAssemblyHandle
- mono_domain_try_type_resolve_typebuilder (MonoDomain *domain, MonoReflectionTypeBuilderHandle typebuilder, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- g_assert (domain);
- g_assert (MONO_HANDLE_BOOL (typebuilder));
- g_assert (error);
- error_init (error);
- MonoMethod * const method = mono_class_get_appdomain_do_type_builder_resolve_method (error);
- goto_if_nok (error, return_null);
- MonoAppDomainHandle appdomain;
- appdomain = MONO_HANDLE_NEW (MonoAppDomain, domain->domain);
- void *args [1];
- args [0] = MONO_HANDLE_RAW (typebuilder);
- MonoObjectHandle ret;
- ret = mono_runtime_invoke_handle (method, MONO_HANDLE_CAST (MonoObject, appdomain), args, error);
- goto_if_nok (error, return_null);
- goto exit;
- return_null:
- ret = NULL_HANDLE;
- exit:
- HANDLE_FUNCTION_RETURN_REF (MonoReflectionAssembly, MONO_HANDLE_CAST (MonoReflectionAssembly, ret));
- }
- #endif
- /**
- * mono_domain_owns_vtable_slot:
- * \returns Whether \p vtable_slot is inside a vtable which belongs to \p domain.
- */
- gboolean
- mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot)
- {
- gboolean res;
- MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain);
- mono_mem_manager_lock (memory_manager);
- res = mono_mempool_contains_addr (memory_manager->mp, vtable_slot);
- mono_mem_manager_unlock (memory_manager);
- return res;
- }
- gboolean
- mono_domain_set_fast (MonoDomain *domain, gboolean force)
- {
- MONO_REQ_GC_UNSAFE_MODE;
- if (!force && domain->state == MONO_APPDOMAIN_UNLOADED)
- return FALSE;
- mono_domain_set_internal_with_options (domain, TRUE);
- return TRUE;
- }
- #ifndef ENABLE_NETCORE
- MonoObjectHandle
- ves_icall_System_AppDomain_GetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoError *error)
- {
- error_init (error);
- if (MONO_HANDLE_IS_NULL (name)) {
- mono_error_set_argument_null (error, "name", "");
- return NULL_HANDLE;
- }
- g_assert (!MONO_HANDLE_IS_NULL (ad));
- MonoDomain *add = MONO_HANDLE_GETVAL (ad, data);
- g_assert (add);
- char *str = mono_string_handle_to_utf8 (name, error);
- return_val_if_nok (error, NULL_HANDLE);
- mono_domain_lock (add);
- MonoAppDomainSetupHandle ad_setup = MONO_HANDLE_NEW (MonoAppDomainSetup, add->setup);
- MonoStringHandle o;
- if (!strcmp (str, "APPBASE"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_base);
- else if (!strcmp (str, "APP_CONFIG_FILE"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, configuration_file);
- else if (!strcmp (str, "DYNAMIC_BASE"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, dynamic_base);
- else if (!strcmp (str, "APP_NAME"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, application_name);
- else if (!strcmp (str, "CACHE_BASE"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, cache_path);
- else if (!strcmp (str, "PRIVATE_BINPATH"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path);
- else if (!strcmp (str, "BINPATH_PROBE_ONLY"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, private_bin_path_probe);
- else if (!strcmp (str, "SHADOW_COPY_DIRS"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_directories);
- else if (!strcmp (str, "FORCE_CACHE_INSTALL"))
- o = MONO_HANDLE_NEW_GET (MonoString, ad_setup, shadow_copy_files);
- else
- o = MONO_HANDLE_NEW (MonoString, (MonoString*)mono_g_hash_table_lookup (add->env, MONO_HANDLE_RAW (name)));
- mono_domain_unlock (add);
- g_free (str);
- return MONO_HANDLE_CAST (MonoObject, o);
- }
- void
- ves_icall_System_AppDomain_SetData (MonoAppDomainHandle ad, MonoStringHandle name, MonoObjectHandle data, MonoError *error)
- {
- error_init (error);
- if (MONO_HANDLE_IS_NULL (name)) {
- mono_error_set_argument_null (error, "name", "");
- return;
- }
- g_assert (!MONO_HANDLE_IS_NULL (ad));
- MonoDomain *add = MONO_HANDLE_GETVAL (ad, data);
- g_assert (add);
- mono_domain_lock (add);
- mono_g_hash_table_insert_internal (add->env, MONO_HANDLE_RAW (name), MONO_HANDLE_RAW (data));
- mono_domain_unlock (add);
- }
- #ifndef ENABLE_NETCORE
- MonoAppDomainSetupHandle
- ves_icall_System_AppDomain_getSetup (MonoAppDomainHandle ad, MonoError *error)
- {
- error_init (error);
- g_assert (!MONO_HANDLE_IS_NULL (ad));
- MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
- g_assert (domain);
- return MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
- }
- #endif
- MonoStringHandle
- ves_icall_System_AppDomain_getFriendlyName (MonoAppDomainHandle ad, MonoError *error)
- {
- error_init (error);
- g_assert (!MONO_HANDLE_IS_NULL (ad));
- MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
- g_assert (domain);
- return mono_string_new_handle (domain, domain->friendly_name, error);
- }
- MonoAppDomainHandle
- ves_icall_System_AppDomain_getCurDomain (MonoError *error)
- {
- error_init (error);
- MonoDomain *add = mono_domain_get ();
- return MONO_HANDLE_NEW (MonoAppDomain, add->domain);
- }
- MonoAppDomainHandle
- ves_icall_System_AppDomain_getRootDomain (MonoError *error)
- {
- error_init (error);
- MonoDomain *root = mono_get_root_domain ();
- return MONO_HANDLE_NEW (MonoAppDomain, root->domain);
- }
- MonoBoolean
- ves_icall_System_CLRConfig_CheckThrowUnobservedTaskExceptions (MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- return domain->throw_unobserved_task_exceptions;
- }
- #endif
- #ifndef ENABLE_NETCORE
- static char*
- get_attribute_value (const gchar **attribute_names,
- const gchar **attribute_values,
- const char *att_name)
- {
- int n;
- for (n = 0; attribute_names [n] != NULL; n++) {
- if (strcmp (attribute_names [n], att_name) == 0)
- return g_strdup (attribute_values [n]);
- }
- return NULL;
- }
- static void
- start_element (GMarkupParseContext *context,
- const gchar *element_name,
- const gchar **attribute_names,
- const gchar **attribute_values,
- gpointer user_data,
- GError **gerror)
- {
- RuntimeConfig *runtime_config = (RuntimeConfig *)user_data;
-
- if (strcmp (element_name, "runtime") == 0) {
- runtime_config->runtime_count++;
- return;
- }
- if (strcmp (element_name, "assemblyBinding") == 0) {
- runtime_config->assemblybinding_count++;
- return;
- }
- if (runtime_config->runtime_count != 1)
- return;
- if (strcmp (element_name, "ThrowUnobservedTaskExceptions") == 0) {
- const char *value = get_attribute_value (attribute_names, attribute_values, "enabled");
- if (value && g_ascii_strcasecmp (value, "true") == 0)
- runtime_config->domain->throw_unobserved_task_exceptions = TRUE;
- }
- if (runtime_config->assemblybinding_count != 1)
- return;
- if (strcmp (element_name, "probing") != 0)
- return;
- g_free (runtime_config->domain->private_bin_path);
- runtime_config->domain->private_bin_path = get_attribute_value (attribute_names, attribute_values, "privatePath");
- if (runtime_config->domain->private_bin_path && !runtime_config->domain->private_bin_path [0]) {
- g_free (runtime_config->domain->private_bin_path);
- runtime_config->domain->private_bin_path = NULL;
- return;
- }
- }
- static void
- end_element (GMarkupParseContext *context,
- const gchar *element_name,
- gpointer user_data,
- GError **gerror)
- {
- RuntimeConfig *runtime_config = (RuntimeConfig *)user_data;
- if (strcmp (element_name, "runtime") == 0)
- runtime_config->runtime_count--;
- else if (strcmp (element_name, "assemblyBinding") == 0)
- runtime_config->assemblybinding_count--;
- }
- static void
- parse_error (GMarkupParseContext *context, GError *gerror, gpointer user_data)
- {
- RuntimeConfig *state = (RuntimeConfig *)user_data;
- const gchar *msg;
- const gchar *filename;
- filename = state && state->filename ? (gchar *) state->filename : "<unknown>";
- msg = gerror && gerror->message ? gerror->message : "";
- g_warning ("Error parsing %s: %s", filename, msg);
- }
- static const GMarkupParser
- mono_parser = {
- start_element,
- end_element,
- NULL,
- NULL,
- parse_error
- };
- void
- mono_domain_set_options_from_config (MonoDomain *domain)
- {
- ERROR_DECL (error);
- gchar *config_file_name = NULL, *text = NULL, *config_file_path = NULL;
- gsize len;
- GMarkupParseContext *context;
- RuntimeConfig runtime_config;
- gint offset;
-
- if (!domain || !domain->setup || !domain->setup->configuration_file)
- return;
- config_file_name = mono_string_to_utf8_checked_internal (domain->setup->configuration_file, error);
- if (!is_ok (error)) {
- mono_error_cleanup (error);
- goto free_and_out;
- }
- config_file_path = mono_portability_find_file (config_file_name, TRUE);
- if (!config_file_path)
- config_file_path = config_file_name;
- if (!g_file_get_contents (config_file_path, &text, &len, NULL))
- goto free_and_out;
- runtime_config.runtime_count = 0;
- runtime_config.assemblybinding_count = 0;
- runtime_config.domain = domain;
- runtime_config.filename = config_file_path;
-
- offset = 0;
- if (len > 3 && text [0] == '\xef' && text [1] == (gchar) '\xbb' && text [2] == '\xbf')
- offset = 3; /* Skip UTF-8 BOM */
- context = g_markup_parse_context_new (&mono_parser, (GMarkupParseFlags)0, &runtime_config, NULL);
- if (g_markup_parse_context_parse (context, text + offset, len - offset, NULL))
- g_markup_parse_context_end_parse (context, NULL);
- g_markup_parse_context_free (context);
- free_and_out:
- g_free (text);
- if (config_file_name != config_file_path)
- g_free (config_file_name);
- g_free (config_file_path);
- }
- #endif
- #ifndef ENABLE_NETCORE
- MonoAppDomainHandle
- ves_icall_System_AppDomain_createDomain (MonoStringHandle friendly_name, MonoAppDomainSetupHandle setup, MonoError *error)
- {
- error_init (error);
- MonoAppDomainHandle ad = MONO_HANDLE_NEW (MonoAppDomain, NULL);
- #ifdef DISABLE_APPDOMAINS
- mono_error_set_not_supported (error, "AppDomain creation is not supported on this runtime.");
- #else
- char *fname;
- fname = mono_string_handle_to_utf8 (friendly_name, error);
- return_val_if_nok (error, ad);
- ad = mono_domain_create_appdomain_internal (fname, setup, error);
- g_free (fname);
- #endif
- return ad;
- }
- #endif
- static gboolean
- add_assembly_to_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoAssembly* assm, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (domain, assm, error);
- goto_if_nok (error, leave);
- MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, assm_obj);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
- }
- static MonoArrayHandle
- get_assembly_array_from_domain (MonoDomain *domain, MonoBoolean refonly, MonoError *error)
- {
- int i;
- GPtrArray *assemblies;
- assemblies = mono_domain_get_assemblies (domain, refonly);
- MonoArrayHandle res = mono_array_new_handle (domain, mono_class_get_assembly_class (), assemblies->len, error);
- goto_if_nok (error, leave);
- for (i = 0; i < assemblies->len; ++i) {
- if (!add_assembly_to_array (domain, res, i, (MonoAssembly *)g_ptr_array_index (assemblies, i), error))
- goto leave;
- }
- leave:
- g_ptr_array_free (assemblies, TRUE);
- return res;
- }
- #ifdef ENABLE_NETCORE
- MonoArrayHandle
- ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalGetLoadedAssemblies (MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- return get_assembly_array_from_domain (domain, FALSE, error);
- }
- #else
- MonoArrayHandle
- ves_icall_System_AppDomain_GetAssemblies (MonoAppDomainHandle ad, MonoBoolean refonly, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
- return get_assembly_array_from_domain (domain, refonly, error);
- }
- #endif
- MonoAssembly*
- mono_try_assembly_resolve (MonoAssemblyLoadContext *alc, const char *fname_raw, MonoAssembly *requesting, gboolean refonly, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- error_init (error);
- MonoAssembly *result = NULL;
- MonoStringHandle fname = mono_string_new_handle (mono_alc_domain (alc), fname_raw, error);
- goto_if_nok (error, leave);
- result = mono_try_assembly_resolve_handle (alc, fname, requesting, refonly, error);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (result);
- }
- MonoAssembly*
- mono_try_assembly_resolve_handle (MonoAssemblyLoadContext *alc, MonoStringHandle fname, MonoAssembly *requesting, gboolean refonly, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoAssembly *ret = NULL;
- MonoDomain *domain = mono_alc_domain (alc);
- char *filename = NULL;
- if (mono_runtime_get_no_exec ())
- goto leave;
- #ifndef ENABLE_NETCORE
- static MonoMethod *method;
- MonoBoolean isrefonly;
- gpointer params [3];
- g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname));
- // FIXME cache?
- method = mono_class_get_method_from_name_checked (mono_class_get_appdomain_class (), "DoAssemblyResolve", -1, 0, error);
- g_assert (method != NULL);
- isrefonly = refonly ? 1 : 0;
- MonoReflectionAssemblyHandle requesting_handle;
- if (requesting) {
- requesting_handle = mono_assembly_get_object_handle (domain, requesting, error);
- goto_if_nok (error, leave);
- }
- params [0] = MONO_HANDLE_RAW (fname);
- params [1] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL;
- params [2] = &isrefonly;
- MonoObject *exc;
- exc = NULL;
- MonoReflectionAssemblyHandle result;
- result = MONO_HANDLE_CAST (MonoReflectionAssembly, MONO_HANDLE_NEW (MonoObject, mono_runtime_try_invoke (method, domain->domain, params, &exc, error)));
- if (!is_ok (error) || exc != NULL) {
- if (is_ok (error))
- mono_error_set_exception_instance (error, (MonoException*)exc);
- goto leave;
- }
- ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL;
- if (ret && !refonly && mono_asmctx_get_kind (&ret->context) == MONO_ASMCTX_REFONLY) {
- /* .NET Framework throws System.IO.FileNotFoundException in this case */
- filename = mono_string_handle_to_utf8 (fname, error);
- mono_error_set_file_not_found (error, filename, "AssemblyResolveEvent handlers cannot return Assemblies loaded for reflection only: %s", filename);
- ret = NULL;
- goto leave;
- }
- #else
- MONO_STATIC_POINTER_INIT (MonoMethod, method)
- ERROR_DECL (local_error);
- static gboolean inited;
- if (!inited) {
- MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
- g_assert (alc_class);
- method = mono_class_get_method_from_name_checked (alc_class, "OnAssemblyResolve", -1, 0, local_error);
- inited = TRUE;
- }
- mono_error_cleanup (local_error);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
- if (!method) {
- ret = NULL;
- goto leave;
- }
- MonoReflectionAssemblyHandle requesting_handle;
- if (requesting) {
- requesting_handle = mono_assembly_get_object_handle (domain, requesting, error);
- goto_if_nok (error, leave);
- }
- gpointer params [2];
- params [0] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL;
- params [1] = MONO_HANDLE_RAW (fname);
- MonoReflectionAssemblyHandle result;
- result = MONO_HANDLE_CAST (MonoReflectionAssembly, mono_runtime_try_invoke_handle (method, NULL_HANDLE, params, error));
- goto_if_nok (error, leave);
- if (MONO_HANDLE_BOOL (result))
- ret = MONO_HANDLE_GETVAL (result, assembly);
- #endif
- leave:
- g_free (filename);
- HANDLE_FUNCTION_RETURN_VAL (ret);
- }
- MonoAssembly *
- mono_domain_assembly_postload_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting,
- MonoAssemblyName *aname,
- gboolean refonly, gboolean postload,
- gpointer user_data,
- MonoError *error_out)
- {
- ERROR_DECL (error);
- MonoAssembly *assembly;
- char *aname_str;
- aname_str = mono_stringify_assembly_name (aname);
- /* FIXME: We invoke managed code here, so there is a potential for deadlocks */
- assembly = mono_try_assembly_resolve (alc, aname_str, requesting, refonly, error);
- g_free (aname_str);
- mono_error_cleanup (error);
- return assembly;
- }
-
- /*
- * LOCKING: assumes assemblies_lock in the domain is already locked.
- */
- static void
- add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
- {
- GSList *tmp;
- gboolean destroy_ht = FALSE;
- g_assert (ass != NULL);
- if (!ass->aname.name)
- return;
- if (!ht) {
- ht = g_hash_table_new (mono_aligned_addr_hash, NULL);
- destroy_ht = TRUE;
- for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
- g_hash_table_add (ht, tmp->data);
- }
- }
- if (!g_hash_table_lookup (ht, ass)) {
- mono_assembly_addref (ass);
- g_hash_table_add (ht, ass);
- domain->domain_assemblies = g_slist_append (domain->domain_assemblies, ass);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to domain %s, ref_count=%d", ass->aname.name, ass, domain->friendly_name, ass->ref_count);
- }
- #ifndef ENABLE_NETCORE
- if (ass->image->references) {
- for (int i = 0; i < ass->image->nreferences; i++) {
- MonoAssembly *ref = ass->image->references [i];
- if (ref && ref != REFERENCE_MISSING) {
- if (!g_hash_table_lookup (ht, ref))
- add_assemblies_to_domain (domain, ref, ht);
- }
- }
- }
- #endif
- if (destroy_ht)
- g_hash_table_destroy (ht);
- }
- /*
- * LOCKING: assumes the ALC's assemblies lock is taken
- */
- #ifdef ENABLE_NETCORE
- static void
- add_assembly_to_alc (MonoAssemblyLoadContext *alc, MonoAssembly *ass)
- {
- GSList *tmp;
- g_assert (ass != NULL);
- if (!ass->aname.name)
- return;
- for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
- if (tmp->data == ass) {
- return;
- }
- }
- mono_assembly_addref (ass);
- // Prepending here will break the test suite with frequent InvalidCastExceptions, so we have to append
- alc->loaded_assemblies = g_slist_append (alc->loaded_assemblies, ass);
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly %s[%p] added to ALC (%p), ref_count=%d", ass->aname.name, ass, (gpointer)alc, ass->ref_count);
- }
- #endif
- static void
- mono_domain_fire_assembly_load_event (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
- {
- HANDLE_FUNCTION_ENTER ();
- g_assert (domain);
- g_assert (assembly);
- #ifdef ENABLE_NETCORE
- MONO_STATIC_POINTER_INIT (MonoMethod, method)
- static gboolean inited;
- if (!inited) {
- ERROR_DECL (local_error);
- MonoClass *alc_class = mono_class_get_assembly_load_context_class ();
- g_assert (alc_class);
- method = mono_class_get_method_from_name_checked (alc_class, "OnAssemblyLoad", -1, 0, local_error);
- mono_error_cleanup (local_error);
- inited = TRUE;
- }
- MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
- if (!method)
- goto exit;
- MonoReflectionAssemblyHandle assembly_handle;
- assembly_handle = mono_assembly_get_object_handle (domain, assembly, error);
- goto_if_nok (error, exit);
- gpointer args [1];
- args [0] = MONO_HANDLE_RAW (assembly_handle);
- mono_runtime_try_invoke_handle (method, NULL_HANDLE, args, error);
- #else
- MonoObjectHandle appdomain = MONO_HANDLE_NEW (MonoObject, &domain->domain->mbr.obj);
- MonoClass *klass = mono_handle_class (appdomain);
- MONO_STATIC_POINTER_INIT (MonoClassField, assembly_load_field)
- assembly_load_field = mono_class_get_field_from_name_full (klass, "AssemblyLoad", NULL);
- g_assert (assembly_load_field);
- MONO_STATIC_POINTER_INIT_END (MonoClassField, assembly_load_field)
- if (!MONO_HANDLE_GET_FIELD_BOOL (appdomain, MonoObject*, assembly_load_field))
- goto exit; // No events waiting to be triggered
- MonoReflectionAssemblyHandle reflection_assembly;
- reflection_assembly = mono_assembly_get_object_handle (domain, assembly, error);
- goto_if_nok (error, exit);
- MONO_STATIC_POINTER_INIT (MonoMethod, assembly_load_method)
- assembly_load_method = mono_class_get_method_from_name_checked (klass, "DoAssemblyLoad", -1, 0, error);
- g_assert (assembly_load_method);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, assembly_load_method)
- void *params [1];
- params [0] = MONO_HANDLE_RAW (reflection_assembly);
- mono_runtime_invoke_handle_void (assembly_load_method, appdomain, params, error);
- #endif
- exit:
- HANDLE_FUNCTION_RETURN ();
- }
- static void
- mono_domain_fire_assembly_load (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, gpointer user_data, MonoError *error_out)
- {
- ERROR_DECL (error);
- MonoDomain *domain = mono_alc_domain (alc);
- g_assert (assembly);
- g_assert (domain);
- if (!MONO_BOOL (domain->domain))
- goto leave; // This can happen during startup
- if (mono_runtime_get_no_exec ())
- goto leave;
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Loading assembly %s (%p) into domain %s (%p) and ALC %p", assembly->aname.name, assembly, domain->friendly_name, domain, alc);
- mono_domain_assemblies_lock (domain);
- #ifdef ENABLE_NETCORE
- mono_alc_assemblies_lock (alc);
- #endif
- add_assemblies_to_domain (domain, assembly, NULL);
- #ifdef ENABLE_NETCORE
- add_assembly_to_alc (alc, assembly);
- mono_alc_assemblies_unlock (alc);
- #endif
- mono_domain_assemblies_unlock (domain);
- if (assembly->context.kind != MONO_ASMCTX_INTERNAL)
- mono_domain_fire_assembly_load_event (domain, assembly, error_out);
- leave:
- mono_error_cleanup (error);
- }
- static gboolean
- mono_domain_asmctx_from_path (const char *fname, MonoAssembly *requesting_assembly, gpointer user_data, MonoAssemblyContextKind *out_asmctx)
- {
- MonoDomain *domain = mono_domain_get ();
- char **search_path = NULL;
- for (search_path = domain->search_path; search_path && *search_path; search_path++) {
- if (mono_path_filename_in_basedir (fname, *search_path)) {
- *out_asmctx = MONO_ASMCTX_DEFAULT;
- return TRUE;
- }
- }
- return FALSE;
- }
- #ifndef ENABLE_NETCORE
- /*
- * LOCKING: Acquires the domain assemblies lock.
- */
- static void
- set_domain_search_path (MonoDomain *domain)
- {
- HANDLE_FUNCTION_ENTER ();
- ERROR_DECL (error);
- MonoAppDomainSetupHandle setup;
- gchar **tmp;
- gchar *search_path = NULL;
- gint npaths = 1;
- gchar **pvt_split = NULL;
- GError *gerror = NULL;
- gint appbaselen = -1;
- /*
- * We use the low-level domain assemblies lock, since this is called from
- * assembly loads hooks, which means this thread might hold the loader lock.
- */
- mono_domain_assemblies_lock (domain);
- if (!MONO_BOOL (domain->setup))
- goto exit;
- setup = MONO_HANDLE_NEW (MonoAppDomainSetup, domain->setup);
- if (domain->search_path && !MONO_HANDLE_GET_BOOL (setup, path_changed))
- goto exit;
- if (!MONO_HANDLE_GET_BOOL (setup, application_base))
- goto exit; // Must set application base to get private path working
-
- if (MONO_HANDLE_GET_BOOL (setup, private_bin_path)) {
- search_path = mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString, setup, private_bin_path), error);
- if (!is_ok (error)) { /*FIXME maybe we should bubble up the error.*/
- g_warning ("Could not decode AppDomain search path since it contains invalid characters");
- goto exit;
- }
- }
-
- if (domain->private_bin_path) {
- if (search_path == NULL)
- search_path = domain->private_bin_path;
- else {
- gchar *tmp2 = search_path;
- search_path = g_strjoin (";", search_path, domain->private_bin_path, (const char*)NULL);
- g_free (tmp2);
- }
- }
-
- if (search_path) {
- /*
- * As per MSDN documentation, AppDomainSetup.PrivateBinPath contains a list of
- * directories relative to ApplicationBase separated by semicolons (see
- * http://msdn2.microsoft.com/en-us/library/system.appdomainsetup.privatebinpath.aspx)
- * The loop below copes with the fact that some Unix applications may use ':' (or
- * System.IO.Path.PathSeparator) as the path search separator. We replace it with
- * ';' for the subsequent split.
- *
- * The issue was reported in bug #81446
- */
- #ifndef TARGET_WIN32
- g_strdelimit (search_path, ':', ';');
- #endif
- pvt_split = g_strsplit (search_path, ";", 1000);
- g_free (search_path);
- for (tmp = pvt_split; *tmp; tmp++, npaths++);
- }
- g_strfreev (domain->search_path);
- domain->search_path = NULL;
- tmp = g_new (gchar*, npaths + 1);
- tmp [npaths] = NULL;
- *tmp = mono_string_handle_to_utf8 (MONO_HANDLE_NEW_GET (MonoString, setup, application_base), error);
- if (!is_ok (error)) {
- g_free (tmp);
- goto exit;
- }
- domain->search_path = tmp;
- /* FIXME: is this needed? */
- if (strncmp (*tmp, "file://", 7) == 0) {
- gchar *file = *tmp;
- gchar *uri = *tmp;
- gchar *tmpuri;
- if (uri [7] != '/')
- uri = g_strdup_printf ("file:///%s", uri + 7);
- tmpuri = uri;
- uri = mono_escape_uri_string (tmpuri);
- *tmp = g_filename_from_uri (uri, NULL, &gerror);
- g_free (uri);
- if (tmpuri != file)
- g_free (tmpuri);
- if (gerror != NULL) {
- g_warning ("%s\n", gerror->message);
- g_error_free (gerror);
- *tmp = file;
- } else {
- g_free (file);
- }
- }
- for (gsize i = 1; pvt_split && i < npaths; i++) {
- if (g_path_is_absolute (pvt_split [i - 1])) {
- tmp [i] = g_strdup (pvt_split [i - 1]);
- } else {
- tmp [i] = g_build_filename (tmp [0], pvt_split [i - 1], (const char*)NULL);
- }
- if (strchr (tmp [i], '.')) {
- gchar *reduced;
- gchar *freeme;
- reduced = mono_path_canonicalize (tmp [i]);
- if (appbaselen == -1)
- appbaselen = strlen (tmp [0]);
- if (strncmp (tmp [0], reduced, appbaselen)) {
- g_free (reduced);
- g_free (tmp [i]);
- tmp [i] = g_strdup ("");
- continue;
- }
- freeme = tmp [i];
- tmp [i] = reduced;
- g_free (freeme);
- }
- }
-
- if (MONO_HANDLE_GET_BOOL (setup, private_bin_path_probe)) {
- g_free (tmp [0]);
- tmp [0] = g_strdup ("");
- }
- MONO_HANDLE_SETVAL (setup, path_changed, MonoBoolean, FALSE);
- exit:
- mono_error_cleanup (error);
- g_strfreev (pvt_split);
- mono_domain_assemblies_unlock (domain);
- HANDLE_FUNCTION_RETURN ();
- }
- #endif
- #ifdef DISABLE_SHADOW_COPY
- gboolean
- mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name)
- {
- return FALSE;
- }
- char *
- mono_make_shadow_copy (const char *filename, MonoError *error)
- {
- error_init (error);
- return (char *) filename;
- }
- #else
- typedef enum {
- SHADOW_COPY_SIBLING_EXT_APPEND,
- SHADOW_COPY_SIBLING_EXT_REPLACE,
- } ShadowCopySiblingExt;
- static
- gchar *
- make_sibling_path (const gchar *path, gint pathlen, const char *extension, ShadowCopySiblingExt extopt)
- {
- gchar *result = NULL;
- switch (extopt) {
- case SHADOW_COPY_SIBLING_EXT_APPEND: {
- result = g_strconcat (path, extension, (const char*)NULL);
- break;
- }
- case SHADOW_COPY_SIBLING_EXT_REPLACE: {
- /* expect path to be a .dll or .exe (or some case insensitive variant) */
- g_assert (pathlen >= 4 && path[pathlen - 4] == '.');
- GString *s = g_string_sized_new (pathlen - 4 + strlen (extension));
- g_string_append_len (s, path, pathlen - 4);
- g_string_append (s, extension);
- result = g_string_free (s, FALSE);
- break;
- }
- default:
- g_assert_not_reached ();
- }
- return result;
- }
- static gboolean
- shadow_copy_sibling (const gchar *src_pristine, gint srclen, const char *extension, ShadowCopySiblingExt extopt, const gchar *target_pristine, gint targetlen)
- {
- gchar *file = NULL;
- gunichar2 *orig = NULL;
- gunichar2 *dest = NULL;
- gboolean copy_result = TRUE;
- gchar *target = NULL;
-
- char *src = make_sibling_path (src_pristine, srclen, extension, extopt);
- if (IS_PORTABILITY_CASE) {
- file = mono_portability_find_file (src, TRUE);
- if (file == NULL)
- goto exit;
- } else if (!g_file_test (src, G_FILE_TEST_IS_REGULAR))
- goto exit;
- orig = g_utf8_to_utf16 (src, strlen (src), NULL, NULL, NULL);
- target = make_sibling_path (target_pristine, targetlen, extension, extopt);
- dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL);
-
- mono_w32file_delete (dest);
- gint32 copy_error;
- copy_result = mono_w32file_copy (orig, dest, TRUE, ©_error);
- /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
- * overwritten when updated in their original locations. */
- if (copy_result)
- copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
- exit:
- g_free (file);
- g_free (orig);
- g_free (dest);
- g_free (src);
- g_free (target);
- return copy_result;
- }
- static gint32
- get_cstring_hash (const char *str)
- {
- const char *p;
- gint32 h = 0;
-
- if (!str || !str [0])
- return 0;
-
- gsize const len = strlen (str);
- p = str;
- for (gsize i = 0; i < len; i++) {
- h = (h << 5) - h + *p;
- p++;
- }
-
- return h;
- }
- /*
- * Returned memory is malloc'd. Called must free it
- */
- static char *
- get_shadow_assembly_location_base (MonoDomain *domain, MonoError *error)
- {
- MonoAppDomainSetup *setup;
- char *cache_path = NULL;
- char *appname = NULL;
- char *userdir = NULL;
- char *location;
- error_init (error);
-
- setup = domain->setup;
- if (setup->cache_path != NULL && setup->application_name != NULL) {
- cache_path = mono_string_to_utf8_checked_internal (setup->cache_path, error);
- return_val_if_nok (error, NULL);
- #ifndef TARGET_WIN32
- {
- gint i;
- for (i = strlen (cache_path) - 1; i >= 0; i--)
- if (cache_path [i] == '\\')
- cache_path [i] = '/';
- }
- #endif
- appname = mono_string_to_utf8_checked_internal (setup->application_name, error);
- if (!is_ok (error)) {
- g_free (cache_path);
- return NULL;
- }
- location = g_build_filename (cache_path, appname, "assembly", "shadow", (const char*)NULL);
- } else {
- userdir = g_strdup_printf ("%s-mono-cachepath", g_get_user_name ());
- location = g_build_filename (g_get_tmp_dir (), userdir, "assembly", "shadow", (const char*)NULL);
- }
- g_free (appname);
- g_free (cache_path);
- g_free (userdir);
- return location;
- }
- static char *
- get_shadow_assembly_location (const char *filename, MonoError *error)
- {
- gint32 hash = 0, hash2 = 0;
- char name_hash [9];
- char path_hash [30];
- char *bname = g_path_get_basename (filename);
- char *dirname = g_path_get_dirname (filename);
- char *location, *tmploc;
- MonoDomain *domain = mono_domain_get ();
- error_init (error);
-
- hash = get_cstring_hash (bname);
- hash2 = get_cstring_hash (dirname);
- g_snprintf (name_hash, sizeof (name_hash), "%08x", hash);
- g_snprintf (path_hash, sizeof (path_hash), "%08x_%08x_%08x", hash ^ hash2, hash2, domain->shadow_serial);
- tmploc = get_shadow_assembly_location_base (domain, error);
- if (!is_ok (error)) {
- g_free (bname);
- g_free (dirname);
- return NULL;
- }
- location = g_build_filename (tmploc, name_hash, path_hash, bname, (const char*)NULL);
- g_free (tmploc);
- g_free (bname);
- g_free (dirname);
- return location;
- }
- static gboolean
- private_file_needs_copying (const char *src, struct stat *sbuf_src, char *dest)
- {
- struct stat sbuf_dest;
- gchar *stat_src;
- gchar *real_src = mono_portability_find_file (src, TRUE);
- if (!real_src)
- stat_src = (gchar*)src;
- else
- stat_src = real_src;
- if (stat (stat_src, sbuf_src) == -1) {
- time_t tnow = time (NULL);
- if (real_src)
- g_free (real_src);
- memset (sbuf_src, 0, sizeof (*sbuf_src));
- sbuf_src->st_mtime = tnow;
- sbuf_src->st_atime = tnow;
- return TRUE;
- }
- if (real_src)
- g_free (real_src);
- if (stat (dest, &sbuf_dest) == -1)
- return TRUE;
-
- if (sbuf_src->st_size == sbuf_dest.st_size &&
- sbuf_src->st_mtime == sbuf_dest.st_mtime)
- return FALSE;
- return TRUE;
- }
- static gboolean
- shadow_copy_create_ini (const char *shadow, const char *filename)
- {
- gunichar2 *u16_ini = NULL;
- gboolean result = FALSE;
- guint32 n;
- HANDLE handle = INVALID_HANDLE_VALUE;
- gchar *full_path = NULL;
- char *dir_name = g_path_get_dirname (shadow);
- char *ini_file = g_build_filename (dir_name, "__AssemblyInfo__.ini", (const char*)NULL);
- g_free (dir_name);
- result = g_file_test (ini_file, G_FILE_TEST_IS_REGULAR);
- if (result)
- goto exit;
- u16_ini = g_utf8_to_utf16 (ini_file, strlen (ini_file), NULL, NULL, NULL);
- if (!u16_ini)
- goto exit;
- handle = mono_w32file_create (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, CREATE_NEW, FileAttributes_Normal);
- if (handle == INVALID_HANDLE_VALUE)
- goto exit;
- full_path = mono_path_resolve_symlinks (filename);
- gint32 win32error;
- win32error = 0;
- result = mono_w32file_write (handle, full_path, strlen (full_path), &n, &win32error);
- exit:
- if (handle != INVALID_HANDLE_VALUE)
- mono_w32file_close (handle);
- g_free (u16_ini);
- g_free (full_path);
- g_free (ini_file);
- return result;
- }
- gboolean
- mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name)
- {
- ERROR_DECL (error);
- MonoAppDomainSetup *setup;
- gchar *all_dirs = NULL;
- gchar **dir_ptr;
- gchar **directories = NULL;
- gchar *shadow_status_string;
- gchar *base_dir = NULL;
- gboolean shadow_enabled;
- gboolean found = FALSE;
- if (domain == NULL)
- goto exit;
- setup = domain->setup;
- if (setup == NULL || setup->shadow_copy_files == NULL)
- goto exit;
- shadow_status_string = mono_string_to_utf8_checked_internal (setup->shadow_copy_files, error);
- if (!is_ok (error))
- goto exit;
- shadow_enabled = !g_ascii_strncasecmp (shadow_status_string, "true", 4);
- g_free (shadow_status_string);
- if (!shadow_enabled)
- goto exit;
- found = (setup->shadow_copy_directories == NULL);
- if (found)
- goto exit;
- /* Is dir_name a shadow_copy destination already? */
- base_dir = get_shadow_assembly_location_base (domain, error);
- if (!is_ok (error))
- goto exit;
- found = strstr (dir_name, base_dir) != 0;
- if (found)
- goto exit;
- all_dirs = mono_string_to_utf8_checked_internal (setup->shadow_copy_directories, error);
- if (!is_ok (error))
- goto exit;
- directories = g_strsplit (all_dirs, G_SEARCHPATH_SEPARATOR_S, 1000);
- dir_ptr = directories;
- while (!found && *dir_ptr) {
- found = (**dir_ptr != '\0' && !strcmp (*dir_ptr, dir_name));
- dir_ptr++;
- }
- exit:
- mono_error_cleanup (error);
- g_free (base_dir);
- g_strfreev (directories);
- g_free (all_dirs);
- return found;
- }
- /*
- This function raises exceptions so it can cause as sorts of nasty stuff if called
- while holding a lock.
- Returns old file name if shadow copy is disabled, new shadow copy file name if successful
- or NULL if source file not found.
- FIXME bubble up the error instead of raising it here
- */
- char *
- mono_make_shadow_copy (const char *filename, MonoError *oerror)
- {
- ERROR_DECL (error);
- gint filename_len, shadow_len;
- gunichar2 *orig, *dest;
- guint32 attrs;
- char *shadow;
- gboolean copy_result;
- struct stat src_sbuf;
- struct utimbuf utbuf;
- char *dir_name = g_path_get_dirname (filename);
- MonoDomain *domain = mono_domain_get ();
- char *shadow_dir;
- gint32 copy_error;
- #ifndef ENABLE_NETCORE
- set_domain_search_path (domain);
- #endif
- if (!mono_is_shadow_copy_enabled (domain, dir_name)) {
- g_free (dir_name);
- return (char *) filename;
- }
- /* Is dir_name a shadow_copy destination already? */
- shadow_dir = get_shadow_assembly_location_base (domain, error);
- if (!is_ok (error)) {
- mono_error_cleanup (error);
- g_free (dir_name);
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in shadow directory name).");
- return NULL;
- }
- if (strstr (dir_name, shadow_dir)) {
- g_free (shadow_dir);
- g_free (dir_name);
- return (char *) filename;
- }
- g_free (shadow_dir);
- g_free (dir_name);
- shadow = get_shadow_assembly_location (filename, error);
- if (!is_ok (error)) {
- mono_error_cleanup (error);
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy (invalid characters in file name).");
- return NULL;
- }
- if (g_ensure_directory_exists (shadow) == FALSE) {
- g_free (shadow);
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy (ensure directory exists).");
- return NULL;
- }
- if (!private_file_needs_copying (filename, &src_sbuf, shadow))
- return (char*) shadow;
- orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL);
- dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL);
- mono_w32file_delete (dest);
- /* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather
- * let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly)
- * and not have it runtime error" */
- attrs = mono_w32file_get_attributes (orig);
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- g_free (shadow);
- return (char *)filename;
- }
- copy_result = mono_w32file_copy (orig, dest, TRUE, ©_error);
- /* Fix for bug #556884 - make sure the files have the correct mode so that they can be
- * overwritten when updated in their original locations. */
- if (copy_result)
- copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
- g_free (dest);
- g_free (orig);
- if (copy_result == FALSE) {
- g_free (shadow);
- /* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */
- if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND || mono_w32error_get_last() == ERROR_PATH_NOT_FOUND)
- return NULL; /* file not found, shadow copy failed */
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy (mono_w32file_copy).");
- return NULL;
- }
- /* attempt to copy .mdb, .pdb and .config if they exist */
- filename_len = strlen (filename);
- shadow_len = strlen (shadow);
- copy_result = shadow_copy_sibling (filename, filename_len, ".mdb", SHADOW_COPY_SIBLING_EXT_APPEND, shadow, shadow_len);
- if (copy_result)
- copy_result = shadow_copy_sibling (filename, filename_len, ".pdb", SHADOW_COPY_SIBLING_EXT_REPLACE, shadow, shadow_len);
- if (copy_result)
- copy_result = shadow_copy_sibling (filename, filename_len, ".config", SHADOW_COPY_SIBLING_EXT_APPEND, shadow, shadow_len);
-
- if (!copy_result) {
- g_free (shadow);
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (mono_w32file_copy).");
- return NULL;
- }
- /* Create a .ini file containing the original assembly location */
- if (!shadow_copy_create_ini (shadow, filename)) {
- g_free (shadow);
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy .ini file.");
- return NULL;
- }
- utbuf.actime = src_sbuf.st_atime;
- utbuf.modtime = src_sbuf.st_mtime;
- utime (shadow, &utbuf);
-
- return shadow;
- }
- #endif /* DISABLE_SHADOW_COPY */
- /**
- * mono_domain_from_appdomain:
- */
- MonoDomain *
- mono_domain_from_appdomain (MonoAppDomain *appdomain_raw)
- {
- HANDLE_FUNCTION_ENTER ();
- MonoDomain *result;
- MONO_ENTER_GC_UNSAFE;
- MONO_HANDLE_DCL (MonoAppDomain, appdomain);
- result = mono_domain_from_appdomain_handle (appdomain);
- MONO_EXIT_GC_UNSAFE;
- HANDLE_FUNCTION_RETURN_VAL (result);
- }
- MonoDomain *
- mono_domain_from_appdomain_handle (MonoAppDomainHandle appdomain)
- {
- #ifndef ENABLE_NETCORE
- HANDLE_FUNCTION_ENTER ();
- MonoDomain *dom = NULL;
- if (MONO_HANDLE_IS_NULL (appdomain))
- goto leave;
- if (mono_class_is_transparent_proxy (mono_handle_class (appdomain))) {
- MonoTransparentProxyHandle tp = MONO_HANDLE_CAST (MonoTransparentProxy, appdomain);
- MonoRealProxyHandle rp = MONO_HANDLE_NEW_GET (MonoRealProxy, tp, rp);
-
- dom = mono_domain_get_by_id (MONO_HANDLE_GETVAL (rp, target_domain_id));
- } else
- dom = MONO_HANDLE_GETVAL (appdomain, data);
- leave:
- HANDLE_FUNCTION_RETURN_VAL (dom);
- #else
- return mono_get_root_domain ();
- #endif
- }
- static gboolean
- try_load_from (MonoAssembly **assembly,
- const gchar *path1, const gchar *path2,
- const gchar *path3, const gchar *path4,
- const MonoAssemblyOpenRequest *req)
- {
- gchar *fullpath;
- gboolean found = FALSE;
-
- *assembly = NULL;
- fullpath = g_build_filename (path1, path2, path3, path4, (const char*)NULL);
- if (IS_PORTABILITY_SET) {
- gchar *new_fullpath = mono_portability_find_file (fullpath, TRUE);
- if (new_fullpath) {
- g_free (fullpath);
- fullpath = new_fullpath;
- found = TRUE;
- }
- } else
- found = g_file_test (fullpath, G_FILE_TEST_IS_REGULAR);
-
- if (found) {
- *assembly = mono_assembly_request_open (fullpath, req, NULL);
- }
- g_free (fullpath);
- return (*assembly != NULL);
- }
- static MonoAssembly *
- real_load (gchar **search_path, const gchar *culture, const gchar *name, const MonoAssemblyOpenRequest *req)
- {
- MonoAssembly *result = NULL;
- gchar **path;
- gchar *filename;
- const gchar *local_culture;
- gint len;
- if (!culture || *culture == '\0') {
- local_culture = "";
- } else {
- local_culture = culture;
- }
- filename = g_strconcat (name, ".dll", (const char*)NULL);
- len = strlen (filename);
- for (path = search_path; *path; path++) {
- if (**path == '\0') {
- continue; /* Ignore empty ApplicationBase */
- }
- /* See test cases in bug #58992 and bug #57710 */
- /* 1st try: [culture]/[name].dll (culture may be empty) */
- strcpy (filename + len - 4, ".dll");
- if (try_load_from (&result, *path, local_culture, "", filename, req))
- break;
- /* 2nd try: [culture]/[name].exe (culture may be empty) */
- strcpy (filename + len - 4, ".exe");
- if (try_load_from (&result, *path, local_culture, "", filename, req))
- break;
- /* 3rd try: [culture]/[name]/[name].dll (culture may be empty) */
- strcpy (filename + len - 4, ".dll");
- if (try_load_from (&result, *path, local_culture, name, filename, req))
- break;
- /* 4th try: [culture]/[name]/[name].exe (culture may be empty) */
- strcpy (filename + len - 4, ".exe");
- if (try_load_from (&result, *path, local_culture, name, filename, req))
- break;
- }
- g_free (filename);
- return result;
- }
- #ifdef ENABLE_NETCORE
- static char *
- get_app_context_base_directory (MonoError *error)
- {
- MONO_STATIC_POINTER_INIT (MonoMethod, get_basedir)
- ERROR_DECL (local_error);
- MonoClass *app_context = mono_class_get_app_context_class ();
- g_assert (app_context);
- get_basedir = mono_class_get_method_from_name_checked (app_context, "get_BaseDirectory", -1, 0, local_error);
- mono_error_assert_ok (local_error);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, get_basedir)
- HANDLE_FUNCTION_ENTER ();
- MonoStringHandle result = MONO_HANDLE_CAST (MonoString, mono_runtime_try_invoke_handle (get_basedir, NULL_HANDLE, NULL, error));
- char *base_dir = mono_string_handle_to_utf8 (result, error);
- HANDLE_FUNCTION_RETURN_VAL (base_dir);
- }
- #endif
- /*
- * Try loading the assembly from ApplicationBase and PrivateBinPath
- * and then from assemblies_path if any.
- * LOCKING: This is called from the assembly loading code, which means the caller
- * might hold the loader lock. Thus, this function must not acquire the domain lock.
- */
- static MonoAssembly *
- mono_domain_assembly_preload (MonoAssemblyLoadContext *alc,
- MonoAssemblyName *aname,
- gchar **assemblies_path,
- gboolean refonly,
- gpointer user_data,
- MonoError *error)
- {
- MonoDomain *domain = mono_alc_domain (alc);
- MonoAssembly *result = NULL;
- #ifdef ENABLE_NETCORE
- g_assert (alc);
- g_assert (domain == mono_domain_get ());
- #endif
- #ifndef ENABLE_NETCORE
- set_domain_search_path (domain);
- #endif
- MonoAssemblyCandidatePredicate predicate = NULL;
- void* predicate_ud = NULL;
- if (mono_loader_get_strict_assembly_name_check ()) {
- predicate = &mono_assembly_candidate_predicate_sn_same_name;
- predicate_ud = aname;
- }
- MonoAssemblyOpenRequest req;
- mono_assembly_request_prepare_open (&req, refonly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_DEFAULT, alc);
- req.request.predicate = predicate;
- req.request.predicate_ud = predicate_ud;
- #ifdef ENABLE_NETCORE
- if (!mono_runtime_get_no_exec ()) {
- char *search_path [2];
- search_path [1] = NULL;
- char *base_dir = get_app_context_base_directory (error);
- search_path [0] = base_dir;
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain (%p) ApplicationBase is %s", domain, base_dir);
- result = real_load (search_path, aname->culture, aname->name, &req);
- g_free (base_dir);
- }
- #else
- if (domain->search_path && domain->search_path [0] != NULL) {
- if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY)) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Domain %s search path is:", domain->friendly_name);
- for (int i = 0; domain->search_path [i]; i++) {
- const char *p = domain->search_path[i];
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "\tpath[%d] = '%s'", i, p);
- }
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "End of domain %s search path.", domain->friendly_name);
- }
- result = real_load (domain->search_path, aname->culture, aname->name, &req);
- }
- #endif
- if (result == NULL && assemblies_path && assemblies_path [0] != NULL) {
- result = real_load (assemblies_path, aname->culture, aname->name, &req);
- }
- return result;
- }
- /*
- * Check whenever a given assembly was already loaded in the current appdomain.
- */
- static MonoAssembly *
- mono_domain_assembly_search (MonoAssemblyLoadContext *alc, MonoAssembly *requesting,
- MonoAssemblyName *aname,
- gboolean refonly,
- gboolean postload,
- gpointer user_data,
- MonoError *error)
- {
- g_assert (aname != NULL);
- GSList *tmp;
- MonoAssembly *ass;
- #ifdef ENABLE_NETCORE
- const MonoAssemblyNameEqFlags eq_flags = MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE;
- mono_alc_assemblies_lock (alc);
- for (tmp = alc->loaded_assemblies; tmp; tmp = tmp->next) {
- ass = (MonoAssembly *)tmp->data;
- g_assert (ass != NULL);
- // FIXME: Can dynamic assemblies match here for netcore?
- if (assembly_is_dynamic (ass) || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags))
- continue;
- mono_alc_assemblies_unlock (alc);
- return ass;
- }
- mono_alc_assemblies_unlock (alc);
- #else
- MonoDomain *domain = mono_alc_domain (alc);
- const gboolean strong_name = aname->public_key_token[0] != 0;
- /* If it's not a strong name, any version that has the right simple
- * name is good enough to satisfy the request. .NET Framework also
- * ignores case differences in this case. */
- const MonoAssemblyNameEqFlags eq_flags = (MonoAssemblyNameEqFlags)((strong_name && !ignore_version_and_key_when_finding_assemblies_already_loaded) ? MONO_ANAME_EQ_IGNORE_CASE :
- (MONO_ANAME_EQ_IGNORE_PUBKEY | MONO_ANAME_EQ_IGNORE_VERSION | MONO_ANAME_EQ_IGNORE_CASE));
- mono_domain_assemblies_lock (domain);
- for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
- ass = (MonoAssembly *)tmp->data;
- g_assert (ass != NULL);
- /* Dynamic assemblies can't match here in MS.NET */
- gboolean ass_ref_only = mono_asmctx_get_kind (&ass->context) == MONO_ASMCTX_REFONLY;
- if (assembly_is_dynamic (ass) || refonly != ass_ref_only || !mono_assembly_names_equal_flags (aname, &ass->aname, eq_flags))
- continue;
- mono_domain_assemblies_unlock (domain);
- return ass;
- }
- mono_domain_assemblies_unlock (domain);
- #endif
- return NULL;
- }
- #if ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_InternalLoad (MonoStringHandle name_handle, MonoStackCrawlMark *stack_mark, gpointer load_Context, MonoError *error)
- {
- error_init (error);
- MonoAssembly *ass = NULL;
- MonoAssemblyName aname;
- MonoAssemblyByNameRequest req;
- MonoAssemblyContextKind asmctx;
- MonoImageOpenStatus status = MONO_IMAGE_OK;
- gboolean parsed;
- char *name;
- MonoAssembly *requesting_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)load_Context;
- if (!alc)
- alc = mono_assembly_get_alc (requesting_assembly);
- if (!alc)
- g_assert_not_reached ();
-
- MonoDomain *domain = mono_alc_domain (alc);
- g_assert (alc);
- asmctx = MONO_ASMCTX_DEFAULT;
- mono_assembly_request_prepare_byname (&req, asmctx, alc);
- req.basedir = NULL;
- /* Everything currently goes through this function, and the postload hook (aka the AppDomain.AssemblyResolve event)
- * is triggered under some scenarios. It's not completely obvious to me in what situations (if any) this should be disabled,
- * other than for corlib satellite assemblies (which I've dealt with further down the call stack).
- */
- //req.no_postload_search = TRUE;
- req.requesting_assembly = requesting_assembly;
- name = mono_string_handle_to_utf8 (name_handle, error);
- goto_if_nok (error, fail);
- parsed = mono_assembly_name_parse (name, &aname);
- g_free (name);
- if (!parsed)
- goto fail;
- MonoAssemblyCandidatePredicate predicate;
- void* predicate_ud;
- predicate = NULL;
- predicate_ud = NULL;
- if (mono_loader_get_strict_assembly_name_check ()) {
- predicate = &mono_assembly_candidate_predicate_sn_same_name;
- predicate_ud = &aname;
- }
- req.request.predicate = predicate;
- req.request.predicate_ud = predicate_ud;
- ass = mono_assembly_request_byname (&aname, &req, &status);
- if (!ass)
- goto fail;
- MonoReflectionAssemblyHandle refass;
- refass = mono_assembly_get_object_handle (domain, ass, error);
- goto_if_nok (error, fail);
- return refass;
- fail:
- return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- }
- #endif
- #ifndef ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_LoadFrom (MonoStringHandle fname, MonoBoolean refOnly, MonoStackCrawlMark *stack_mark, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = mono_domain_get ();
- char *name, *filename;
- MonoImageOpenStatus status = MONO_IMAGE_OK;
- MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- name = NULL;
- if (MONO_HANDLE_IS_NULL (fname)) {
- mono_error_set_argument_null (error, "assemblyFile", "");
- goto leave;
- }
-
- name = filename = mono_string_handle_to_utf8 (fname, error);
- goto_if_nok (error, leave);
-
- MonoAssembly *requesting_assembly;
- requesting_assembly = NULL;
- if (!refOnly)
- requesting_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- MonoAssembly *ass;
- MonoAssemblyOpenRequest req;
- mono_assembly_request_prepare_open (&req, refOnly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_LOADFROM, mono_domain_default_alc (domain));
- req.requesting_assembly = requesting_assembly;
- ass = mono_assembly_request_open (filename, &req, &status);
-
- if (!ass) {
- if (status == MONO_IMAGE_IMAGE_INVALID)
- mono_error_set_bad_image_by_name (error, name, "Invalid Image: %s", name);
- else
- mono_error_set_simple_file_not_found (error, name, refOnly);
- goto leave;
- }
- result = mono_assembly_get_object_handle (domain, ass, error);
- leave:
- g_free (name);
- return result;
- }
- #endif
- static
- MonoAssembly *
- mono_alc_load_file (MonoAssemblyLoadContext *alc, MonoStringHandle fname, MonoAssembly *executing_assembly, MonoAssemblyContextKind asmctx, MonoError *error)
- {
- MonoAssembly *ass = NULL;
- HANDLE_FUNCTION_ENTER ();
- char *filename = NULL;
- if (MONO_HANDLE_IS_NULL (fname)) {
- mono_error_set_argument_null (error, "assemblyFile", "");
- goto leave;
- }
- filename = mono_string_handle_to_utf8 (fname, error);
- goto_if_nok (error, leave);
- if (!g_path_is_absolute (filename)) {
- mono_error_set_argument (error, "assemblyFile", "Absolute path information is required.");
- goto leave;
- }
- MonoImageOpenStatus status;
- MonoAssemblyOpenRequest req;
- mono_assembly_request_prepare_open (&req, asmctx, alc);
- req.requesting_assembly = executing_assembly;
- ass = mono_assembly_request_open (filename, &req, &status);
- if (!ass) {
- if (status == MONO_IMAGE_IMAGE_INVALID)
- mono_error_set_bad_image_by_name (error, filename, "Invalid Image: %s", filename);
- else
- mono_error_set_simple_file_not_found (error, filename, asmctx == MONO_ASMCTX_REFONLY);
- }
- leave:
- g_free (filename);
- HANDLE_FUNCTION_RETURN_VAL (ass);
- }
- #ifndef ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- ves_icall_System_Reflection_Assembly_LoadFile_internal (MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get ();
- MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- MonoAssembly *executing_assembly;
- executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- MonoAssembly *ass = mono_alc_load_file (mono_domain_default_alc (domain), fname, executing_assembly, MONO_ASMCTX_INDIVIDUAL, error);
- goto_if_nok (error, leave);
- result = mono_assembly_get_object_handle (domain, ass, error);
- leave:
- return result;
- }
- #else
- MonoReflectionAssemblyHandle
- ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFile (gpointer alc_ptr, MonoStringHandle fname, MonoStackCrawlMark *stack_mark, MonoError *error)
- {
- MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)alc_ptr;
- MonoDomain *domain = mono_alc_domain (alc);
- MonoAssembly *executing_assembly;
- executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- MonoAssembly *ass = mono_alc_load_file (alc, fname, executing_assembly, mono_alc_is_default (alc) ? MONO_ASMCTX_LOADFROM : MONO_ASMCTX_INDIVIDUAL, error);
- goto_if_nok (error, leave);
- result = mono_assembly_get_object_handle (domain, ass, error);
- leave:
- return result;
- }
- #endif
- static MonoAssembly*
- mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *raw_assembly, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error);
- #ifdef ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalLoadFromStream (gpointer native_alc, gpointer raw_assembly_ptr, gint32 raw_assembly_len, gpointer raw_symbols_ptr, gint32 raw_symbols_len, MonoError *error)
- {
- MonoAssemblyLoadContext *alc = (MonoAssemblyLoadContext *)native_alc;
- MonoDomain *domain = mono_alc_domain (alc);
- MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- MonoAssembly *assm = NULL;
- assm = mono_alc_load_raw_bytes (alc, (guint8 *)raw_assembly_ptr, raw_assembly_len, (guint8 *)raw_symbols_ptr, raw_symbols_len, FALSE, error);
- goto_if_nok (error, leave);
- result = mono_assembly_get_object_handle (domain, assm, error);
- leave:
- return result;
- }
- #else
- MonoReflectionAssemblyHandle
- ves_icall_System_AppDomain_LoadAssemblyRaw (MonoAppDomainHandle ad,
- MonoArrayHandle raw_assembly,
- MonoArrayHandle raw_symbol_store, MonoObjectHandle evidence,
- MonoBoolean refonly,
- MonoError *error)
- {
- MonoAssembly *ass;
- MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
- MonoAssemblyLoadContext *alc = mono_domain_default_alc (domain);
- guint8 *raw_assembly_ptr = (guint8 *)mono_array_handle_addr (raw_assembly, sizeof (guint8), 0);
- guint32 raw_assembly_len = mono_array_handle_length (raw_assembly);
- guint8 *raw_symbols_ptr = NULL;
- guint32 raw_symbols_len = 0;
- if (!MONO_HANDLE_IS_NULL (raw_symbol_store)) {
- raw_symbols_ptr = (guint8 *)mono_array_handle_addr (raw_symbol_store, sizeof (guint8), 0);
- raw_symbols_len = mono_array_handle_length (raw_symbol_store);
- }
- ass = mono_alc_load_raw_bytes (alc, raw_assembly_ptr, raw_assembly_len, raw_symbols_ptr, raw_symbols_len, refonly, error);
- goto_if_nok (error, leave);
- refass = mono_assembly_get_object_handle (domain, ass, error);
- if (!MONO_HANDLE_IS_NULL (refass))
- MONO_HANDLE_SET (refass, evidence, evidence);
- leave:
- return refass;
- }
- #endif /* ENABLE_NETCORE */
- static MonoAssembly*
- mono_alc_load_raw_bytes (MonoAssemblyLoadContext *alc, guint8 *assembly_data, guint32 raw_assembly_len, guint8 *raw_symbol_data, guint32 raw_symbol_len, gboolean refonly, MonoError *error)
- {
- MonoAssembly *ass = NULL;
- MonoImageOpenStatus status;
- MonoImage *image = mono_image_open_from_data_internal (alc, (char*)assembly_data, raw_assembly_len, TRUE, NULL, refonly, FALSE, NULL, NULL);
- if (!image) {
- mono_error_set_bad_image_by_name (error, "In memory assembly", "0x%p", assembly_data);
- return ass;
- }
- if (raw_symbol_data)
- mono_debug_open_image_from_memory (image, raw_symbol_data, raw_symbol_len);
- #ifndef ENABLE_NETCORE
- MonoAssembly* redirected_asm = NULL;
- MonoImageOpenStatus new_status = MONO_IMAGE_OK;
- // http://blogs.microsoft.co.il/sasha/2010/06/09/assemblyreflectiononlyload-ignores-assembly-binding-redirects/
- if (!refonly && (redirected_asm = mono_assembly_binding_applies_to_image (alc, image, &new_status))) {
- mono_image_close (image);
- image = redirected_asm->image;
- mono_image_addref (image); /* so that mono_image close, below, has something to do */
- } else if (new_status != MONO_IMAGE_OK) {
- mono_image_close (image);
- mono_error_set_bad_image_by_name (error, "In Memory assembly", "0x%p was assembly binding redirected to another assembly that failed to load", assembly_data);
- return ass;
- }
- #endif
- MonoAssemblyLoadRequest req;
- mono_assembly_request_prepare_load (&req, refonly? MONO_ASMCTX_REFONLY : MONO_ASMCTX_INDIVIDUAL, alc);
- ass = mono_assembly_request_load_from (image, "", &req, &status);
- if (!ass) {
- mono_image_close (image);
- mono_error_set_bad_image_by_name (error, "In Memory assembly", "0x%p", assembly_data);
- return ass;
- }
- /* Clear the reference added by mono_image_open_from_data_internal above */
- mono_image_close (image);
- return ass;
- }
- #ifndef ENABLE_NETCORE
- MonoReflectionAssemblyHandle
- ves_icall_System_AppDomain_LoadAssembly (MonoAppDomainHandle ad, MonoStringHandle assRef, MonoObjectHandle evidence, MonoBoolean refOnly, MonoStackCrawlMark *stack_mark, MonoError *error)
- {
- MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
- MonoImageOpenStatus status = MONO_IMAGE_OK;
- MonoAssembly *ass;
- MonoAssemblyName aname;
- gchar *name = NULL;
- gboolean parsed;
- g_assert (!MONO_HANDLE_IS_NULL (assRef));
- name = mono_string_handle_to_utf8 (assRef, error);
- goto_if_nok (error, fail);
- parsed = mono_assembly_name_parse (name, &aname);
- g_free (name);
- if (!parsed) {
- MonoReflectionAssemblyHandle refass = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- /* This is a parse error... */
- if (!refOnly) {
- MonoAssembly *assm = mono_try_assembly_resolve_handle (mono_domain_default_alc (domain), assRef, NULL, refOnly, error);
- goto_if_nok (error, fail);
- if (assm) {
- refass = mono_assembly_get_object_handle (domain, assm, error);
- goto_if_nok (error, fail);
- }
- }
- return refass;
- }
- MonoAssemblyContextKind asmctx;
- asmctx = refOnly ? MONO_ASMCTX_REFONLY : MONO_ASMCTX_DEFAULT;
- const char *basedir;
- basedir = NULL;
- if (!refOnly) {
- /* Determine if the current assembly is in LoadFrom context.
- * If it is, we must include the executing assembly's basedir
- * when probing for the given assembly name, and also load the
- * requested assembly in LoadFrom context.
- */
- MonoAssembly *executing_assembly = mono_runtime_get_caller_from_stack_mark (stack_mark);
- if (executing_assembly && mono_asmctx_get_kind (&executing_assembly->context) == MONO_ASMCTX_LOADFROM) {
- asmctx = MONO_ASMCTX_LOADFROM;
- basedir = executing_assembly->basedir;
- }
- }
- MonoAssemblyByNameRequest req;
- mono_assembly_request_prepare_byname (&req, asmctx, mono_domain_default_alc (domain));
- req.basedir = basedir;
- req.no_postload_search = TRUE;
- ass = mono_assembly_request_byname (&aname, &req, &status);
- mono_assembly_name_free_internal (&aname);
- if (!ass) {
- /* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
- if (!refOnly) {
- ass = mono_try_assembly_resolve_handle (mono_domain_default_alc (domain), assRef, NULL, refOnly, error);
- goto_if_nok (error, fail);
- }
- if (!ass)
- goto fail;
- }
- g_assert (ass);
- MonoReflectionAssemblyHandle refass;
- refass = mono_assembly_get_object_handle (domain, ass, error);
- goto_if_nok (error, fail);
- MONO_HANDLE_SET (refass, evidence, evidence);
- return refass;
- fail:
- return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
- }
- void
- ves_icall_System_AppDomain_InternalUnload (gint32 domain_id, MonoError *error)
- {
- MonoDomain * domain = mono_domain_get_by_id (domain_id);
- if (NULL == domain) {
- mono_error_set_execution_engine (error, "Failed to unload domain, domain id not found");
- return;
- }
-
- if (domain == mono_get_root_domain ()) {
- mono_error_set_generic_error (error, "System", "CannotUnloadAppDomainException", "The default appdomain can not be unloaded.");
- return;
- }
- /*
- * Unloading seems to cause problems when running NUnit/NAnt, hence
- * this workaround.
- */
- if (g_hasenv ("MONO_NO_UNLOAD"))
- return;
- MonoException *exc = NULL;
- mono_domain_try_unload (domain, (MonoObject**)&exc, NULL);
- if (exc)
- mono_error_set_exception_instance (error, exc);
- }
- MonoBoolean
- ves_icall_System_AppDomain_InternalIsFinalizingForUnload (gint32 domain_id, MonoError *error)
- {
- MonoDomain *domain = mono_domain_get_by_id (domain_id);
- if (!domain)
- return TRUE;
- return mono_domain_is_unloading (domain);
- }
- void
- ves_icall_System_AppDomain_DoUnhandledException (MonoAppDomainHandle ad, MonoExceptionHandle exc, MonoError *error)
- {
- mono_unhandled_exception_checked (MONO_HANDLE_CAST (MonoObject, exc), error);
- mono_error_assert_ok (error);
- }
- gint32
- ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomainHandle ad,
- MonoReflectionAssemblyHandle refass, MonoArrayHandle args,
- MonoError *error)
- {
- MonoImage *image;
- MonoMethod *method;
- g_assert (!MONO_HANDLE_IS_NULL (refass));
- MonoAssembly *assembly = MONO_HANDLE_GETVAL (refass, assembly);
- image = assembly->image;
- g_assert (image);
- method = mono_get_method_checked (image, mono_image_get_entry_point (image), NULL, NULL, error);
- if (!method)
- g_error ("No entry point method found in %s due to %s", image->name, mono_error_get_message (error));
- if (MONO_HANDLE_IS_NULL (args)) {
- MonoDomain *domain = MONO_HANDLE_GETVAL (ad, data);
- MONO_HANDLE_ASSIGN (args , mono_array_new_handle (domain, mono_defaults.string_class, 0, error));
- mono_error_assert_ok (error);
- }
- int res = mono_runtime_exec_main_checked (method, MONO_HANDLE_RAW (args), error);
- return res;
- }
- MonoAppDomainHandle
- ves_icall_System_AppDomain_InternalSetDomain (MonoAppDomainHandle ad, MonoError* error)
- {
- error_init (error);
- MonoDomain *old_domain = mono_domain_get ();
- if (!mono_domain_set_fast (MONO_HANDLE_GETVAL (ad, data), FALSE)) {
- mono_error_set_appdomain_unloaded (error);
- return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE);
- }
- return MONO_HANDLE_NEW (MonoAppDomain, old_domain->domain);
- }
- MonoAppDomainHandle
- ves_icall_System_AppDomain_InternalSetDomainByID (gint32 domainid, MonoError *error)
- {
- MonoDomain *current_domain = mono_domain_get ();
- MonoDomain *domain = mono_domain_get_by_id (domainid);
- if (!domain || !mono_domain_set_fast (domain, FALSE)) {
- mono_error_set_appdomain_unloaded (error);
- return MONO_HANDLE_CAST (MonoAppDomain, NULL_HANDLE);
- }
- return MONO_HANDLE_NEW (MonoAppDomain, current_domain->domain);
- }
- void
- ves_icall_System_AppDomain_InternalPushDomainRef (MonoAppDomainHandle ad, MonoError *error)
- {
- error_init (error);
- mono_thread_push_appdomain_ref (MONO_HANDLE_GETVAL (ad, data));
- }
- void
- ves_icall_System_AppDomain_InternalPushDomainRefByID (gint32 domain_id, MonoError *error)
- {
- error_init (error);
- MonoDomain *domain = mono_domain_get_by_id (domain_id);
- if (!domain) {
- /*
- * Raise an exception to prevent the managed code from executing a pop
- * later.
- */
- mono_error_set_appdomain_unloaded (error);
- return;
- }
- mono_thread_push_appdomain_ref (domain);
- }
- void
- ves_icall_System_AppDomain_InternalPopDomainRef (MonoError *error)
- {
- error_init (error);
- mono_thread_pop_appdomain_ref ();
- }
- MonoAppContextHandle
- ves_icall_System_AppDomain_InternalGetContext (MonoError *error)
- {
- error_init (error);
- return mono_context_get_handle ();
- }
- MonoAppContextHandle
- ves_icall_System_AppDomain_InternalGetDefaultContext (MonoError *error)
- {
- error_init (error);
- return MONO_HANDLE_NEW (MonoAppContext, mono_domain_get ()->default_context);
- }
- MonoAppContextHandle
- ves_icall_System_AppDomain_InternalSetContext (MonoAppContextHandle mc, MonoError *error)
- {
- error_init (error);
- MonoAppContextHandle old_context = mono_context_get_handle ();
- mono_context_set_handle (mc);
- return old_context;
- }
- MonoStringHandle
- ves_icall_System_AppDomain_InternalGetProcessGuid (MonoStringHandle newguid, MonoError *error)
- {
- error_init (error);
- MonoDomain* mono_root_domain = mono_get_root_domain ();
- mono_domain_lock (mono_root_domain);
- if (process_guid_set) {
- mono_domain_unlock (mono_root_domain);
- return mono_string_new_utf16_handle (mono_domain_get (), process_guid, sizeof(process_guid)/2, error);
- }
- MonoGCHandle gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, newguid), TRUE);
- memcpy (process_guid, mono_string_chars_internal (MONO_HANDLE_RAW (newguid)), sizeof(process_guid));
- mono_gchandle_free_internal (gchandle);
- process_guid_set = TRUE;
- mono_domain_unlock (mono_root_domain);
- return newguid;
- }
- #endif
- /**
- * mono_domain_is_unloading:
- */
- gboolean
- mono_domain_is_unloading (MonoDomain *domain)
- {
- if (domain->state == MONO_APPDOMAIN_UNLOADING || domain->state == MONO_APPDOMAIN_UNLOADED)
- return TRUE;
- else
- return FALSE;
- }
- #ifndef ENABLE_NETCORE
- static void
- clear_cached_vtable (MonoVTable *vtable)
- {
- MonoClass *klass = vtable->klass;
- MonoDomain *domain = vtable->domain;
- MonoClassRuntimeInfo *runtime_info;
- void *data;
- runtime_info = m_class_get_runtime_info (klass);
- if (runtime_info && runtime_info->max_domain >= domain->domain_id)
- runtime_info->domain_vtables [domain->domain_id] = NULL;
- if (m_class_has_static_refs (klass) && (data = mono_vtable_get_static_field_data (vtable)))
- mono_gc_free_fixed (data);
- }
- static G_GNUC_UNUSED void
- zero_static_data (MonoVTable *vtable)
- {
- MonoClass *klass = vtable->klass;
- void *data;
- if (m_class_has_static_refs (klass) && (data = mono_vtable_get_static_field_data (vtable)))
- mono_gc_bzero_aligned (data, mono_class_data_size (klass));
- }
- typedef struct unload_data {
- gboolean done;
- MonoDomain *domain;
- char *failure_reason;
- gint32 refcount;
- } unload_data;
- static void
- unload_data_unref (unload_data *data)
- {
- if (!data)
- return;
- gint32 count;
- do {
- mono_atomic_load_acquire (count, gint32, &data->refcount);
- g_assert (count >= 1 && count <= 2);
- if (count == 1) {
- g_free (data);
- return;
- }
- } while (mono_atomic_cas_i32 (&data->refcount, count - 1, count) != count);
- }
- static void
- deregister_reflection_info_roots_from_list (MonoImage *image)
- {
- GSList *list = image->reflection_info_unregister_classes;
- while (list) {
- MonoClass *klass = (MonoClass *)list->data;
- mono_class_free_ref_info (klass);
- list = list->next;
- }
- image->reflection_info_unregister_classes = NULL;
- }
- static void
- deregister_reflection_info_roots (MonoDomain *domain)
- {
- GSList *list;
- mono_domain_assemblies_lock (domain);
- for (list = domain->domain_assemblies; list; list = list->next) {
- MonoAssembly *assembly = (MonoAssembly *)list->data;
- MonoImage *image = assembly->image;
- int i;
- /*
- * No need to take the image lock here since dynamic images are appdomain bound and
- * at this point the mutator is gone. Taking the image lock here would mean
- * promoting it from a simple lock to a complex lock, which we better avoid if
- * possible.
- */
- if (image_is_dynamic (image))
- deregister_reflection_info_roots_from_list (image);
- for (i = 0; i < image->module_count; ++i) {
- MonoImage *module = image->modules [i];
- if (module && image_is_dynamic (module))
- deregister_reflection_info_roots_from_list (module);
- }
- }
- mono_domain_assemblies_unlock (domain);
- }
- static gsize WINAPI
- unload_thread_main (void *arg)
- {
- unload_data *data = (unload_data*)arg;
- MonoDomain *domain = data->domain;
- MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain);
- int i;
- gsize result = 1; // failure
- mono_thread_set_name_constant_ignore_error (mono_thread_internal_current (), "Domain unloader", MonoSetThreadNameFlag_Permanent);
- /*
- * FIXME: Abort our parent thread last, so we can return a failure
- * indication if aborting times out.
- */
- if (!mono_threads_abort_appdomain_threads (domain, -1)) {
- data->failure_reason = g_strdup_printf ("Aborting of threads in domain %s timed out.", domain->friendly_name);
- goto failure;
- }
- if (!mono_threadpool_remove_domain_jobs (domain, -1)) {
- data->failure_reason = g_strdup_printf ("Cleanup of threadpool jobs of domain %s timed out.", domain->friendly_name);
- goto failure;
- }
- /* Finalize all finalizable objects in the doomed appdomain */
- if (!mono_domain_finalize (domain, -1)) {
- data->failure_reason = g_strdup_printf ("Finalization of domain %s timed out.", domain->friendly_name);
- goto failure;
- }
- /* Clear references to our vtables in class->runtime_info.
- * We also hold the loader lock because we're going to change
- * class->runtime_info.
- */
- mono_loader_lock ();
- mono_domain_lock (domain);
- mono_mem_manager_lock (memory_manager);
- /*
- * We need to make sure that we don't have any remsets
- * pointing into static data of the to-be-freed domain because
- * at the next collections they would be invalid. So what we
- * do is we first zero all static data and then do a minor
- * collection. Because all references in the static data will
- * now be null we won't do any unnecessary copies and after
- * the collection there won't be any more remsets.
- */
- for (i = 0; i < memory_manager->class_vtable_array->len; ++i)
- zero_static_data ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i));
- #if !HAVE_BOEHM_GC
- mono_gc_collect (0);
- #endif
- for (i = 0; i < memory_manager->class_vtable_array->len; ++i)
- clear_cached_vtable ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i));
- deregister_reflection_info_roots (domain);
- mono_assembly_cleanup_domain_bindings (domain->domain_id);
- mono_mem_manager_unlock (memory_manager);
- mono_domain_unlock (domain);
- mono_loader_unlock ();
- domain->state = MONO_APPDOMAIN_UNLOADED;
- /* printf ("UNLOADED %s.\n", domain->friendly_name); */
- /* remove from the handle table the items related to this domain */
- mono_gchandle_free_domain (domain);
- mono_domain_free (domain, FALSE);
- result = 0; // success
- exit:
- mono_atomic_store_release (&data->done, TRUE);
- unload_data_unref (data);
- return result;
- failure:
- result = 1;
- goto exit;
- }
- /**
- * mono_domain_unload:
- * \param domain The domain to unload
- *
- * Unloads an appdomain. Follows the process outlined in the comment
- * for \c mono_domain_try_unload.
- */
- void
- mono_domain_unload (MonoDomain *domain)
- {
- MONO_ENTER_GC_UNSAFE;
- MonoObject *exc = NULL;
- mono_domain_try_unload (domain, &exc, NULL);
- MONO_EXIT_GC_UNSAFE;
- }
- static MonoThreadInfoWaitRet
- guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable)
- {
- MonoThreadInfoWaitRet result;
- MONO_ENTER_GC_SAFE;
- result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable);
- MONO_EXIT_GC_SAFE;
- return result;
- }
- /**
- * mono_domain_try_unload:
- * \param domain The domain to unload
- * \param exc Exception information
- *
- * Unloads an appdomain. Follows the process outlined in:
- * http://blogs.gotdotnet.com/cbrumme
- *
- * If doing things the 'right' way is too hard or complex, we do it the
- * 'simple' way, which means do everything needed to avoid crashes and
- * memory leaks, but not much else.
- *
- * It is required to pass a valid reference to the exc argument, upon return
- * from this function *exc will be set to the exception thrown, if any.
- *
- * If this method is not called from an icall (embedded scenario for instance),
- * it must not be called with any managed frames on the stack, since the unload
- * process could end up trying to abort the current thread.
- */
- void
- mono_domain_try_unload (MonoDomain *domain, MonoObject **exc, MonoUnityExceptionFunc callback)
- {
- HANDLE_FUNCTION_ENTER ();
- ERROR_DECL (error);
- MonoThreadHandle *thread_handle = NULL;
- MonoAppDomainState prev_state;
- MonoMethod *method;
- unload_data *thread_data = NULL;
- MonoInternalThreadHandle internal;
- MonoDomain *caller_domain = mono_domain_get ();
- /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
- /* Atomically change our state to UNLOADING */
- prev_state = (MonoAppDomainState)mono_atomic_cas_i32 ((gint32*)&domain->state,
- MONO_APPDOMAIN_UNLOADING_START,
- MONO_APPDOMAIN_CREATED);
- if (prev_state != MONO_APPDOMAIN_CREATED) {
- switch (prev_state) {
- case MONO_APPDOMAIN_UNLOADING_START:
- case MONO_APPDOMAIN_UNLOADING:
- *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already being unloaded.");
- goto exit;
- case MONO_APPDOMAIN_UNLOADED:
- *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain ("Appdomain is already unloaded.");
- goto exit;
- default:
- g_warning ("Invalid appdomain state %d", prev_state);
- g_assert_not_reached ();
- }
- }
- mono_domain_set_fast (domain, FALSE);
- /* Notify OnDomainUnload listeners */
- method = mono_class_get_method_from_name_checked (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload", -1, 0, error);
- g_assert (method);
- mono_runtime_try_invoke (method, domain->domain, NULL, exc, error);
- if (!is_ok (error)) {
- if (*exc)
- mono_error_cleanup (error);
- else
- *exc = (MonoObject*)mono_error_convert_to_exception (error);
- }
- if (*exc) {
- if (callback != NULL)
- callback (*exc);
- else {
- /* Roll back the state change */
- domain->state = MONO_APPDOMAIN_CREATED;
- mono_domain_set_internal_with_options (caller_domain, TRUE);
- goto exit;
- }
- }
- mono_domain_set_fast (caller_domain, FALSE);
- thread_data = g_new0 (unload_data, 1);
- thread_data->domain = domain;
- thread_data->failure_reason = NULL;
- thread_data->done = FALSE;
- thread_data->refcount = 2; /*Must be 2: unload thread + initiator */
- /*The managed callback finished successfully, now we start tearing down the appdomain*/
- domain->state = MONO_APPDOMAIN_UNLOADING;
- /*
- * First we create a separate thread for unloading, since
- * we might have to abort some threads, including the current one.
- *
- * Have to attach to the runtime so shutdown can wait for this thread.
- *
- * Force it to be attached to avoid racing during shutdown.
- */
- internal = mono_thread_create_internal_handle (mono_get_root_domain (), unload_thread_main, thread_data, MONO_THREAD_CREATE_FLAGS_FORCE_CREATE, error);
- mono_error_assert_ok (error);
- thread_handle = mono_threads_open_thread_handle (MONO_HANDLE_GETVAL (internal, handle));
- /* Wait for the thread */
- while (!thread_data->done && guarded_wait (thread_handle, MONO_INFINITE_WAIT, TRUE) == MONO_THREAD_INFO_WAIT_RET_ALERTED) {
- if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) {
- /* The unload thread tries to abort us */
- /* The icall wrapper will execute the abort */
- goto exit;
- }
- }
- if (thread_data->failure_reason) {
- /* Roll back the state change */
- domain->state = MONO_APPDOMAIN_CREATED;
- g_warning ("%s", thread_data->failure_reason);
- *exc = (MonoObject *) mono_get_exception_cannot_unload_appdomain (thread_data->failure_reason);
- g_free (thread_data->failure_reason);
- thread_data->failure_reason = NULL;
- }
- exit:
- mono_threads_close_thread_handle (thread_handle);
- unload_data_unref (thread_data);
- HANDLE_FUNCTION_RETURN ();
- }
- #endif /* ENABLE_NETCORE */
- #ifdef ENABLE_NETCORE
- /* Remember properties so they can be be installed in AppContext during runtime init */
- void
- mono_runtime_register_appctx_properties (int nprops, const char **keys, const char **values)
- {
- n_appctx_props = nprops;
- appctx_keys = g_new0 (gunichar2*, nprops);
- appctx_values = g_new0 (gunichar2*, nprops);
- for (int i = 0; i < nprops; ++i) {
- appctx_keys [i] = g_utf8_to_utf16 (keys [i], strlen (keys [i]), NULL, NULL, NULL);
- appctx_values [i] = g_utf8_to_utf16 (values [i], strlen (values [i]), NULL, NULL, NULL);
- }
- }
- static GENERATE_GET_CLASS_WITH_CACHE (appctx, "System", "AppContext")
- /* Install properties into AppContext */
- void
- mono_runtime_install_appctx_properties (void)
- {
- ERROR_DECL (error);
- gpointer args [3];
- MonoMethod *setup = mono_class_get_method_from_name_checked (mono_class_get_appctx_class (), "Setup", 3, 0, error);
- g_assert (setup);
- // FIXME: TRUSTED_PLATFORM_ASSEMBLIES is very large
- /* internal static unsafe void Setup(char** pNames, char** pValues, int count) */
- args [0] = appctx_keys;
- args [1] = appctx_values;
- args [2] = &n_appctx_props;
- mono_runtime_invoke_checked (setup, NULL, args, error);
- mono_error_assert_ok (error);
- /* No longer needed */
- for (int i = 0; i < n_appctx_props; ++i) {
- g_free (appctx_keys [i]);
- g_free (appctx_values [i]);
- }
- g_free (appctx_keys);
- g_free (appctx_values);
- appctx_keys = NULL;
- appctx_values = NULL;
- }
- #endif
|