Skip to content

Commit 9c341f4

Browse files
[release/6.0] Allow runtimeconfig StartupHooks and Environment StartupHooks to both be present (#62124)
* Allow configProperties "STARTUP_HOOKS" and env "DOTNET_STARTUP_HOOKS" to both be present * Fix duplicate_property_error property names to reflect the actual duplicate * fixup! Allow configProperties "STARTUP_HOOKS" and env "DOTNET_STARTUP_HOOKS" to both be present * Enforce env startup hook precedence over runtimeconfig startup hooks Co-authored-by: Tom de Goede <tom.degoede@afas.nl>
1 parent 5d465ac commit 9c341f4

2 files changed

Lines changed: 70 additions & 6 deletions

File tree

src/installer/tests/HostActivation.Tests/StartupHooks.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class StartupHooks : IClassFixture<StartupHooks.SharedTestState>
1313
{
1414
private SharedTestState sharedTestState;
1515
private string startupHookVarName = "DOTNET_STARTUP_HOOKS";
16+
private string startupHookRuntimeConfigName = "STARTUP_HOOKS";
1617
private string startupHookSupport = "System.StartupHookProvider.IsSupported";
1718

1819
public StartupHooks(StartupHooks.SharedTestState fixture)
@@ -105,6 +106,64 @@ public void Muxer_activation_of_Multiple_StartupHooks_Succeeds()
105106
.And.HaveStdOutContaining("Hello World");
106107
}
107108

109+
[Fact]
110+
public void Muxer_activation_of_RuntimeConfig_StartupHook_Succeeds()
111+
{
112+
var fixture = sharedTestState.PortableAppFixture.Copy();
113+
var dotnet = fixture.BuiltDotnet;
114+
var appDll = fixture.TestProject.AppDll;
115+
116+
var startupHookFixture = sharedTestState.StartupHookFixture.Copy();
117+
var startupHookDll = startupHookFixture.TestProject.AppDll;
118+
119+
RuntimeConfig.FromFile(fixture.TestProject.RuntimeConfigJson)
120+
.WithProperty(startupHookRuntimeConfigName, startupHookDll)
121+
.Save();
122+
123+
// RuntimeConfig defined startup hook
124+
dotnet.Exec(appDll)
125+
.CaptureStdOut()
126+
.CaptureStdErr()
127+
.Execute()
128+
.Should().Pass()
129+
.And.HaveStdOutContaining("Hello from startup hook!")
130+
.And.HaveStdOutContaining("Hello World");
131+
}
132+
133+
[Fact]
134+
public void Muxer_activation_of_RuntimeConfig_And_Environment_StartupHooks_SucceedsInExpectedOrder()
135+
{
136+
var fixture = sharedTestState.PortableAppFixture.Copy();
137+
var dotnet = fixture.BuiltDotnet;
138+
var appDll = fixture.TestProject.AppDll;
139+
140+
var startupHookFixture = sharedTestState.StartupHookFixture.Copy();
141+
var startupHookDll = startupHookFixture.TestProject.AppDll;
142+
143+
RuntimeConfig.FromFile(fixture.TestProject.RuntimeConfigJson)
144+
.WithProperty(startupHookRuntimeConfigName, startupHookDll)
145+
.Save();
146+
147+
var startupHook2Fixture = sharedTestState.StartupHookWithDependencyFixture.Copy();
148+
var startupHook2Dll = startupHook2Fixture.TestProject.AppDll;
149+
150+
// include any char to counter output from other threads such as in #57243
151+
const string wildcardPattern = @"[\r\n\s.]*";
152+
153+
// RuntimeConfig and Environment startup hooks in expected order
154+
dotnet.Exec(appDll)
155+
.EnvironmentVariable(startupHookVarName, startupHook2Dll)
156+
.CaptureStdOut()
157+
.CaptureStdErr()
158+
.Execute()
159+
.Should().Pass()
160+
.And.HaveStdOutMatching("Hello from startup hook with dependency!" +
161+
wildcardPattern +
162+
"Hello from startup hook!" +
163+
wildcardPattern +
164+
"Hello World");
165+
}
166+
108167
// Empty startup hook variable
109168
[Fact]
110169
public void Muxer_activation_of_Empty_StartupHook_Variable_Succeeds()

src/native/corehost/hostpolicy/hostpolicy_context.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,16 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
287287
pal::string_t startup_hooks;
288288
if (pal::getenv(_X("DOTNET_STARTUP_HOOKS"), &startup_hooks))
289289
{
290-
if (!coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str()))
290+
const pal::char_t *config_startup_hooks;
291+
if (coreclr_properties.try_get(common_property::StartUpHooks, &config_startup_hooks))
291292
{
292-
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
293-
return StatusCode::LibHostDuplicateProperty;
293+
// env startup hooks shoold have precedence over config startup hooks
294+
// therefore append config_startup_hooks AFTER startup_hooks
295+
startup_hooks.push_back(PATH_SEPARATOR);
296+
startup_hooks.append(config_startup_hooks);
294297
}
298+
299+
coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str());
295300
}
296301

297302
// Single-File Bundle Probe
@@ -303,7 +308,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
303308

304309
if (!coreclr_properties.add(common_property::BundleProbe, ptr_stream.str().c_str()))
305310
{
306-
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
311+
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::BundleProbe));
307312
return StatusCode::LibHostDuplicateProperty;
308313
}
309314
}
@@ -318,7 +323,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
318323

319324
if (!coreclr_properties.add(common_property::PInvokeOverride, ptr_stream.str().c_str()))
320325
{
321-
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
326+
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::PInvokeOverride));
322327
return StatusCode::LibHostDuplicateProperty;
323328
}
324329
}
@@ -327,7 +332,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a
327332
#if defined(HOSTPOLICY_EMBEDDED)
328333
if (!coreclr_properties.add(common_property::HostPolicyEmbedded, _X("true")))
329334
{
330-
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks));
335+
log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::HostPolicyEmbedded));
331336
return StatusCode::LibHostDuplicateProperty;
332337
}
333338
#endif

0 commit comments

Comments
 (0)