Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Enable mono runtime to handle SIGTERM like CoreCLR #82806 - #82813

Closed
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm
Closed

Enable mono runtime to handle SIGTERM like CoreCLR #82806#82813
nealef wants to merge 6 commits into
dotnet:mainfrom
nealef:sigterm

Conversation

@nealef

Copy link
Copy Markdown
Contributor

Provide fix for #81093 - "Mono does not emit ProcessExit event on SIGTERM"

  • src/mono/mono/mini/mini-posix.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-windows.c

    • Add signal handler for SIGTERM
  • src/mono/mono/mini/mini-runtime.c

    • Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable to be monitored by the GC finalizer thread
  • src/mono/mono/mini/mini-runtime.h

    • Define prototype for mono_sigterm_signal_handler()
  • src/mono/mono/metadata/gc.c

    • Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
    • Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.

…on SIGTERM"
* src/mono/mono/mini/mini-posix.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-windows.c
- Add signal handler for SIGTERM
* src/mono/mono/mini/mini-runtime.c
- Add mono_sigterm_signal_handler to process SIGTERM that will set a global variable
to be monitored by the GC finalizer thread
* src/mono/mono/mini/mini-runtime.h
- Define prototype for mono_sigterm_signal_handler()
* src/mono/mono/metadata/gc.c
- Monitor for sigterm and kick off the shutdown process when encountered by calling mono_runtime_try_shutdown().
- Exit with either the user set exitcode (System.Environment.ExitCode) or SIGTERM + 128.
@ghostghost added community-contribution Indicates that the PR has been added by a community member area-VM-meta-mono labels Mar 1, 2023
@vargaz

Copy link
Copy Markdown
Contributor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Users expect the process to terminate when it's sent a SIGTERM, and adding a handler for that could cause the process to get stuck if the managed code gets stuck etc.

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

@tmds

tmds commented Mar 13, 2023

Copy link
Copy Markdown
Member

What does coreCLR do in this situation? It fields the SIGTERM and invokes managed code. How does it prevent getting stuck?

It doesn't.

The user code may prevent the application from terminating, for example by blocking the ProcessExit event.

SIGTERM is a friendly request for an app to terminate.

If it doesn't terminate in a timely fashion, the user can send it SIGKILL.

That's what a control process, like systemd will do.

@nealef can you remove the following line, which skips the SigTermExitCode test on Mono:

[ActiveIssue("https://github.com/dotnet/runtime/issues/31656",TestRuntimes.Mono)]

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The SigTermExitCode test is failing, because Environment.ExitCode changes aren't getting picked up.

I think the fix may be something like: call mono_environment_exitcode_set(128+SIGTERM) at the start of mono_sigterm_signal_handler, and call exit(mono_environment_exitcode_get() after mono_runtime_try_shutdown.

 - Set a default exit code before starting the SIGTERM processing
Comment threadsrc/mono/mono/mini/mini-runtime.c
Comment threadsrc/mono/mono/metadata/gc.c Outdated
 - Set a default exit code before setting the term_signaled variable that gets checked in gc
 - Simplify use of exit code now that a default is being set
@nealef

nealef commented Mar 14, 2023 via email

Copy link
Copy Markdown
ContributorAuthor

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

Thanks.

Let's see if the test passes for all cases with these changes.

@tmds

tmds commented Mar 14, 2023

Copy link
Copy Markdown
Member

The test is passing for all cases. So it has the right behavior now concerning the ExitCode.

I'm not familiar enough with mono to approve the implementation.

@lambdageeklambdageek left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. couple minor nits.

Comment threadsrc/mono/mono/mini/mini-runtime.c Outdated
Comment threadsrc/mono/mono/mini/mini-windows.c Outdated
Comment threadsrc/mono/mono/metadata/gc.c Outdated
@lambdageek

Copy link
Copy Markdown
Member

Not sure what's up with (Build mono minijit Pri0 Runtime Tests Run windows x64 release) - might be related?

ping @lateralusX

 - Rename term_signaled to match mono style
- Remove volatile attribute
- Move testing of shutdown until after the sem wait
* src/mono/mono/mini/mini-runtime.c
- Rename term_signaled to mono_term_signaled
* src/mono/mono/mini/mini-windows.c
- Use the correct signal for handler
win32_seh_set_handler(SIGFPE, mono_sigfpe_signal_handler);
win32_seh_set_handler(SIGILL, mono_crashing_signal_handler);
win32_seh_set_handler(SIGSEGV, mono_sigsegv_signal_handler);
win32_seh_set_handler(SIGTERM, mono_sigterm_signal_handler);

@lateralusXlateralusXMar 15, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is going to work on Windows we also need to handle that signal in win32_seh_set_handler as well as react to the exception that will be generated and passed to seh_vectored_exception_handler.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding the case SIGTERM and the corresponding term_handler variable in exceptions_[x86|amd64] appears straightforward but how are they then used? I see there is exception handling for EXCEPTION_ILLEGAL_INSTRUCTION etc. where the handler is picked up and called, but how and where would this particular signal be fielded?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lateralusX@lambdageek Looking for further guidance on the outstanding Windows' issue.

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On windows there is no direct mapping with "SIGTERM", the closest we have is the probably SetConsoleCtrlHandler and mapping different scenarios like done by:

This is how its handled by CoreCLR:

::SetConsoleCtrlHandler(DbgCtrlCHandler, TRUE/*add*/);

So for Mono Windows handling of "SIGTERM" it probably need to setup a console ctrl handler and then react on the event as part of that handler and can't be handled through existing vectorized exception handling logic.

wait = TRUE;

/* Just in case we've received a SIGTERM */
if (mono_term_signaled) {

@lateralusXlateralusXApr 11, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is updated from a different thread without any locking, maybe we would need a read memory barrier to make sure we see updated value, especially when wait == FALSE,. There might be one hidden in the mono_coop_sem_timedwait, looks like at least sem_trywait seems to issue memory barriers, and other implementations probably do as well (like WaitForSingleObjectEx), so maybe not needed in the end, but we depend on implementation details. I guess we can leave it as is for now, just wanted to make a comment/note around potential but adding a read barrier in that code path shouldn't be too dramatic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that at one point, this PR had mono_term_signaled as volatile.

Maybe that (or something else) is needed to ensure these lines don't reorder, causing the wrong exit code to be picked up.

This is how the exit code is set:

mono_environment_exitcode_set(128+SIGTERM);	/* Set default exit code */
mono_term_signaled = TRUE;

@lateralusXlateralusXApr 17, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can always do acquire/release semantics on mono_term_signaled and we would make sure this is not reordered by compiler or CPU. Just using volatile on mono_term_signaled will only prevent compiler to reorder load/store but CPU is still free to do load/store reorder.

@nealef

Copy link
Copy Markdown
ContributorAuthor

Closing this as a new PR was generated that includes Windows has been created: #100056

@nealefnealef closed this Mar 21, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-VM-meta-monocommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@nealef@vargaz@tmds@lambdageek@lateralusX