diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 4e506b95c9746b..60ad5503cfb2ab 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -433,6 +433,7 @@ static int run(const configuration& config) argv_utf8.get(), entry_assembly_utf8.c_str(), (uint32_t*)&exit_code); + if (FAILED(result)) { pal::fprintf(stderr, W("BEGIN: coreclr_execute_assembly failed - Error: 0x%08x\n"), result); diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 7f156f991c3039..138bd4c6c600cb 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -1381,7 +1381,7 @@ void RunManagedStartup() managedStartup.Call(args); } -INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads) +void Assembly::ExecuteMainMethodPre(BOOL waitForOtherThreads) { CONTRACTL { @@ -1397,9 +1397,6 @@ INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThre // reset the error code for std C errno=0; - HRESULT hr = S_OK; - INT32 iRetVal = 0; - Thread *pThread = GetThread(); MethodDesc *pMeth; { @@ -1446,6 +1443,74 @@ INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThre RunManagedStartup(); + Thread::CleanUpForManagedThreadInNative(pThread); + } + } + + //RunMainPost is supposed to be called on the main thread of an EXE, + //after that thread has finished doing useful work. It contains logic + //to decide when the process should get torn down. So, don't call it from + // AppDomain.ExecuteAssembly() + if (pMeth) { + if (waitForOtherThreads) + RunMainPost(); + } + else { + StackSString displayName; + GetDisplayName(displayName); + COMPlusThrowHR(COR_E_MISSINGMETHOD, IDS_EE_FAILED_TO_FIND_MAIN, displayName); + } + +} + +INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads) +{ + CONTRACTL + { + INSTANCE_CHECK; + THROWS; + GC_TRIGGERS; + MODE_ANY; + ENTRY_POINT; + INJECT_FAULT(COMPlusThrowOM()); + } + CONTRACTL_END; + + // reset the error code for std C + errno=0; + + HRESULT hr = S_OK; + INT32 iRetVal = 0; + + Thread *pThread = GetThread(); + MethodDesc *pMeth; + { + // This thread looks like it wandered in -- but actually we rely on it to keep the process alive. + pThread->SetBackground(FALSE); + + GCX_COOP(); + + pMeth = GetEntryPoint(); + + if (pMeth) { + { +#ifdef FEATURE_COMINTEROP + GCX_PREEMP(); + + Thread::ApartmentState state = Thread::AS_Unknown; + state = SystemDomain::GetEntryPointThreadAptState(pMeth->GetMDImport(), pMeth->GetMemberDef()); + SystemDomain::SetThreadAptState(state); +#endif // FEATURE_COMINTEROP + } + + RunMainPre(); + + // Perform additional managed thread initialization. + // This would is normally done in the runtime when a managed + // thread is started, but is done here instead since the + // Main thread wasn't started by the runtime. + Thread::InitializationForManagedThreadInNative(pThread); + hr = RunMain(pMeth, 1, &iRetVal, stringArgs); Thread::CleanUpForManagedThreadInNative(pThread); diff --git a/src/coreclr/vm/assembly.hpp b/src/coreclr/vm/assembly.hpp index 987b7231b0a40a..4edbdc38d003a2 100644 --- a/src/coreclr/vm/assembly.hpp +++ b/src/coreclr/vm/assembly.hpp @@ -251,6 +251,7 @@ class Assembly //**************************************************************************************** // + void ExecuteMainMethodPre(BOOL waitForOtherThreads); INT32 ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads); //**************************************************************************************** diff --git a/src/coreclr/vm/assemblynative.cpp b/src/coreclr/vm/assemblynative.cpp index bf549e77346b25..3746273c0719f4 100644 --- a/src/coreclr/vm/assemblynative.cpp +++ b/src/coreclr/vm/assemblynative.cpp @@ -1170,6 +1170,19 @@ extern "C" void QCALLTYPE AssemblyNative_GetEntryAssembly(QCall::ObjectHandleOnS END_QCALL; } +extern "C" void QCALLTYPE AssemblyNative_UpdateEntryAssembly(QCall::AssemblyHandle assemblyHandle) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + Assembly* pAssembly = assemblyHandle->GetAssembly(); + PTR_AppDomain pCurDomain = GetAppDomain(); + pCurDomain->SetRootAssembly(pAssembly); + + END_QCALL; +} + extern "C" void QCALLTYPE AssemblyNative_GetImageRuntimeVersion(QCall::AssemblyHandle pAssembly, QCall::StringHandleOnStack retString) { QCALL_CONTRACT; diff --git a/src/coreclr/vm/assemblynative.hpp b/src/coreclr/vm/assemblynative.hpp index 80ae3da8c2bd59..11ffdf593e4cc9 100644 --- a/src/coreclr/vm/assemblynative.hpp +++ b/src/coreclr/vm/assemblynative.hpp @@ -42,6 +42,8 @@ extern "C" uint32_t QCALLTYPE AssemblyNative_GetAssemblyCount(); extern "C" void QCALLTYPE AssemblyNative_GetEntryAssembly(QCall::ObjectHandleOnStack retAssembly); +extern "C" void QCALLTYPE AssemblyNative_UpdateEntryAssembly(QCall::AssemblyHandle assemblyHandle); + extern "C" void QCALLTYPE AssemblyNative_GetExecutingAssembly(QCall::StackCrawlMarkHandle stackMark, QCall::ObjectHandleOnStack retAssembly); diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index b85331e00ce8d2..05194fe35e8cd2 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -337,7 +337,10 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, if(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_Corhost_Swallow_Uncaught_Exceptions)) { EX_TRY - DWORD retval = pAssembly->ExecuteMainMethod(&arguments, TRUE /* waitForOtherThreads */); + pAssembly->ExecuteMainMethodPre(TRUE /* waitForOtherThreads */); + AppDomain *curDomain = SystemDomain::GetCurrentDomain(); + Assembly *curEntryAssembly = curDomain->GetRootAssembly(); + DWORD retval = curEntryAssembly->ExecuteMainMethod(&arguments, TRUE /* waitForOtherThreads */); if (pReturnValue) { *pReturnValue = retval; @@ -346,7 +349,10 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, } else { - DWORD retval = pAssembly->ExecuteMainMethod(&arguments, TRUE /* waitForOtherThreads */); + pAssembly->ExecuteMainMethodPre(TRUE /* waitForOtherThreads */); + AppDomain *curDomain = SystemDomain::GetCurrentDomain(); + Assembly *curEntryAssembly = curDomain->GetRootAssembly(); + DWORD retval = curEntryAssembly->ExecuteMainMethod(&arguments, TRUE /* waitForOtherThreads */); if (pReturnValue) { *pReturnValue = retval; diff --git a/src/mono/sample/HelloWorld_2/HelloWorld_2.csproj b/src/mono/sample/HelloWorld_2/HelloWorld_2.csproj new file mode 100644 index 00000000000000..cc052494b398fa --- /dev/null +++ b/src/mono/sample/HelloWorld_2/HelloWorld_2.csproj @@ -0,0 +1,61 @@ + + + Exe + $(NetCoreAppCurrent) + + true + + + + + + + <_AotOutputType>Library + <_AotLibraryFormat>Dylib + false + + + + + + + + + + + + + + + + true + + + + + + + + + + diff --git a/src/mono/sample/HelloWorld_2/Makefile b/src/mono/sample/HelloWorld_2/Makefile new file mode 100644 index 00000000000000..17138fc5e87c7d --- /dev/null +++ b/src/mono/sample/HelloWorld_2/Makefile @@ -0,0 +1,34 @@ +TOP=../../../../ +DOTNET:=$(TOP)dotnet.sh +DOTNET_Q_ARGS=--nologo -v:q -consoleloggerparameters:NoSummary + +MONO_CONFIG?=Debug +MONO_ARCH?=$(shell . $(TOP)eng/common/native/init-os-and-arch.sh && echo $${arch}) +TARGET_OS?=$(shell . $(TOP)eng/common/native/init-os-and-arch.sh && echo $${os}) +AOT?=false +USE_LLVM?=false +StripILCode?=false +TrimmingEligibleMethodsOutputDirectory?= # + +#MIBC_PROFILE_PATH= + +MONO_ENV_OPTIONS ?= + +publish: + $(DOTNET) publish \ + -c $(MONO_CONFIG) \ + -r $(TARGET_OS)-$(MONO_ARCH) \ + /p:RunAOTCompilation=$(AOT) \ + /p:MonoEnableLLVM=$(USE_LLVM) \ + /p:StripILCode=$(StripILCode) \ + /p:TrimmingEligibleMethodsOutputDirectory=$(TrimmingEligibleMethodsOutputDirectory) \ + '/p:MibcProfilePath="$(MIBC_PROFILE_PATH)"' \ + /bl + +run: publish + DOTNET_DebugWriteToStdErr=1 \ + MONO_ENV_OPTIONS="$(MONO_ENV_OPTIONS)" \ + $(TOP)artifacts/bin/HelloWorld_2/$(MONO_ARCH)/$(MONO_CONFIG)/$(TARGET_OS)-$(MONO_ARCH)/publish/HelloWorld_2 + +clean: + rm -rf $(TOP)artifacts/bin/HelloWorld_2/ diff --git a/src/mono/sample/HelloWorld_2/Program.cs b/src/mono/sample/HelloWorld_2/Program.cs new file mode 100644 index 00000000000000..c083eba935b9e2 --- /dev/null +++ b/src/mono/sample/HelloWorld_2/Program.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace HelloWorld_2 +{ + internal class Program + { + private static void Main(string[] args) + { + Console.WriteLine($"Hello World 2"); + } + } +}