Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Third party code may remove cancel keypress handler #30464

Open
Tracked by #64487
paralaxsd opened this issue Aug 2, 2019 · 2 comments
Open
Tracked by #64487

Third party code may remove cancel keypress handler #30464

paralaxsd opened this issue Aug 2, 2019 · 2 comments

Comments

@paralaxsd
Copy link

Hi,
I have an issue with the way the Console.CancelKeyPress event is implemented:

In my scenario I'm running a vanilla ASP.Net Core 2.2 web application. The web application internally adds a ctrl-c handler and gracefully shuts down the application when ctrl-c is pressed.

Now I had to add some logic to the application that's run in a Java VM via JNI. It seems that initializing JNI registers a SIGINT handler that throws away the console ctrl-c handler registered by ASP.Net.
Pressing ctrl-c when JNI is initialized immediately exits the process even leaving zombie processes behind on Linux.

I looked into the implementation of Console.CancelKeyPress and found that it uses an internal helper type ConsolePal.ControlCHandlerRegistrar that's only registering a ctrl-c handler on the first usage of event addition. On subsequent event additions only the cancel callbacks are chained together.

In my scenario this means that after JNI init I can no longer use Console.CancelKeyPress because it will not re-register the handler and throw the JNI handler out.

I have a workaround for this issue but it depends on private reflection. It sets Console.s_registrar to null and registers a dummy ctrl-c handler in order to throw out the JNI handler. Naturally this approach can break any day when the implementation changes and so I'd appreciate any help in this matter.

var consoleType = typeof(Console);
var registrar = consoleType.GetField("s_registrar", BindingFlags.Static | BindingFlags.NonPublic);

if (registrar != null)
{
	registrar.SetValue(null, null);

	void Dummy(object o, ConsoleCancelEventArgs e) { }
	Console.CancelKeyPress += Dummy;
}

Thanks!

Edit: Unfortunately the workaround above does not work on Linux. I've validated it on Windows with dotnet core 2.2.101.

Edit 2: I found that on Linux a workaround for this issue is to retrieve the current SIGINT handler before a problematic native call and restore if afterwards. E.g.:

#include <signal.h>
// ...
struct sigaction oldAct = {0};
sigaction(SIGINT, nullptr, &oldAct);

// a third party call that changes the SIGINT handler
const long flag = JNI_CreateJavaVM(&vm, reinterpret_cast<void**>(&env), &vmArgs);

sigaction(SIGINT, &oldAct, nullptr);
@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the 5.0 milestone Feb 1, 2020
@maryamariyan maryamariyan added the untriaged New issue has not been triaged by the area owner label Feb 23, 2020
@adamsitnik
Copy link
Member

Hi @paralaxsd

Thank you for detailed report!

I am not familiar with JNI and I've one question: is it running within the same process or a different process on the same VM?

Thanks,
Adam

@adamsitnik adamsitnik modified the milestones: 5.0.0, Future Jun 24, 2020
@paralaxsd
Copy link
Author

paralaxsd commented Jun 24, 2020

I am not familiar with JNI and I've one question: is it running within the same process or a different process on the same VM?

Hi Adam,

In the scenario I've described a JNI VM was created in-process via PInvoke. Initializing JNI is really just an example of any piece of (third party) native code replacing the ctrl-c handler which leaves Console.CancelKeyPress unable to continue working properly afterwards.

@adamsitnik adamsitnik removed the untriaged New issue has not been triaged by the area owner label Jul 6, 2020
@adamsitnik adamsitnik modified the milestones: Future, 6.0.0 Aug 14, 2020
@adamsitnik adamsitnik modified the milestones: 6.0.0, 7.0.0 Jul 26, 2021
@jeffhandley jeffhandley modified the milestones: 7.0.0, Future Jul 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants
@jeffhandley @maryamariyan @adamsitnik @paralaxsd @msftgits and others