-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Add System.IO.Signals.Unix #15178
Comments
does this need https://github.com/dotnet/coreclr/issues/2688 to be finished first? |
No, it shouldn't. |
We need API proposal |
Does "We need API proposal" actually count as managing this issue? (Are you really managing one of the largest and most out of control projects at Microsoft using GitHub tags @karelz? Folksonomy doesn't even scale to the average knitting blog.) Isn't this just a couple of event handlers? Where do you want to put the non-obvious ones?
|
@chadwackerman I am not sure what exactly is your question here. You can learn more about formal API proposals. All docs should be linked from project root.
Possibly, that's exactly what we expect from API proposal - someone to think deeply about it and propose API with story about it (why, how, what, rejected alternatives, etc.). Please let's stay technical (see contributor code of conduct). |
Is there a tag link I can click on that shows items waiting for an API proposal? I don't see one here. And are you seriously (and silently!) asking the community to map signal.h to an enum and delegates? Microsoft already owns shipping code that does this. It's called Mono. You can click the linked issues around Unix signals in this GitHub project and it takes you in a circle, with nobody doing anything. You can actually use the PowerBI GitHub adaptor to show that Microsoft employees are (I hope unconsciously!) blocking on one another. It's almost as bad as those Microsoft Support sites where three Microsoft subcontractors upvote each other's wrong answers. (But hey, the time to close metrics sure look great!) With all due respect I think the process here is failing you. Somebody needs to take ownership of an issue, not just tag and link to other issues. Meanwhile... I'm running a service on Azure Batch and it actually returns "success" from a cloud batch job if the exit code is nonzero. Why? Because Robocopy sometimes returns a 1 to indicate success. I'm trying to use the OneDriveSDK and the devs there swear it works cross platform and close issues. But it has dependencies on WinForms and STAThread so it doesn't even work in IIS let alone the command line on Linux. Either you're gonna support Linux or not. Perhaps starting with signal.h and honoring 0=success as a return code from main is a good start? .NET already whiffed on arg[0] being the name of the app, but maybe we can slowly turn this boat around. But I don't believe the solution is a few more captains and a lot more tagging. |
All api-needs-work items are API additions which are not api-approved and not api-ready-for-review (see API review process)
We are seriously (and loudly!) asking anyone who will grab this issue to provide a proposal -- it may be MS employee or it may be community member, we are treating people equally in this matter. If it is a simple mapping of signal.h, then be it. Maybe it is more complicated. (I don't know, because I didn't look deeper into the issue - that's what the person grabbing it is supposed to do)
Leveraging Mono code/design is very reasonable approach. We also do it where it helps. Whoever gets to work on this one first is free to consider it.
I am not sure which link-circles you refer to, but even the Milestone set to Future on this issue is supposed to set the expectation that CoreFX team does not consider it as something must-have for next version (2.0), so the "nobody doing anything" is expected at least from MS employees. If community members believe we are misjudging the priority, we encourage them to either contribute or help us understand the impact of the issue better (in a constructive polite way please).
Never tried PowerBI adaptor. I am not sure how it would help us. @chadwackerman maybe it will be a surprise to you, but we (CoreFX teams) are not bunch of lazy or ignorant engineers. We are trying to do the right things the right way. I can't force you to believe that, but I will at least ask you to be constructive and technical in your criticism -- we are open to arguments and discussions. Throwing in general statements and unfounded accusations is not going to help anyone (and I plan to stop responding to them, potentially start deleting them). On the other hand, if someone truly wants to understand the motivation for our process or repo organization, I'll be very happy to explain (and eventually adjust docs to capture it). We are also open to feedback on the process/docs, especially if it is feedback supported by larger part of our community.
Until the issue is assigned to someone it does not have an "owner". The area experts help watch over all issues in their areas and help identify bugs which might have been incorrectly prioritized or where new information arises from the discussion.
I don't see how it is related to this issue.
Please work with their team. CoreFX is not the right place to raise that issue.
I fail to see how it is relevant to this issue. If you think there is a bug in .NET Core apps returning non-0 value by default, please file it as separate issues and let it be discussed on its own. Let's not entangle issues together please, unless they are truly relevant e.g. in overall end-to-end impact. |
@chadwackerman If you want to give them feedback about their process or file a bug you can always open a new issue about it but please don't derail the issue at hand. p.s. Just a piece of friendly advice, you can lose the attitude, no one awe you anything. |
@eyalsk This isn't a hobbyist's blog engine, this is a core technology from a company worth nearly half a trillion dollars. They're charging me by the minute to run my Linux dotnet apps and they very much do owe me something. Among the other candy-colored rectangles I see "up for grabs" and "backlog" but "only 7 votes" and "not expected for v2.0." Meanwhile there's many related bugs and lots of StackOverflow traffic when you Google the issue, which is how I landed here. Apparently I need to build a political action committee or hire lobbyists since we're voting on technology now? We have a senior Microsoft manager who chimes in with "We need API proposal" - end of sentence, no punctuation. The unintentional effect of which is Cookie Licking as it appears the true answer is "Yes, we are expecting the community to solve signal.h despite everyone from Satya down to Scott Hanselman saying we're all aboard the Linux train."
There's a LOT of really amateurish stuff going on at the command line with the various Microsoft teams and it doesn't surprise me that nobody is jumping in to tackle this issue. "return 0" means success, stop hooking my app's signals with your wonky libraries without letting me override, and maybe cut down on the verbosity of the compilers because what it spits out reads like second year college projects where you can feel the youthful excitement seeping out of the passively-voiced text: "Project will be compiled because inputs were modified... Project will be compiled because expected outputs are missing... Time elapsed 00:00:02.2927068" I realize .NET format strings are confusing but sheesh, this ain't the Carnegie Mellon University Pascal compiler lab circa 1990 fellas. |
Can you create a new issue about your problem?
Can you create a new issue about it? i.e. giving them feedback about their process.
Can you create a new issue about it?
Same as above.
Same as above
Same as above. I'm sure they will want to know about the problems you're having. |
@eyalsk I'm sure you're the first guy to grab the Scrabble box for rules clarifications. Unfortunately adding another five tiny issues to the massive backlog here is unlikely to move the needle. Which if you'll take a few minutes away from your busy schedule spent starring repositories for no reason, you may realize indicates a bigger problem with the process here. Thus my raising the issue the way I did. We're dealing with serious technical issues by clicking TiVo thumbs up/down buttons and there's a grown man who works at Microsoft getting stock awards for taking it seriously and parroting four word responses back to us. Moreover there is no sane path to discuss strategic issues which pushes all this toward the inevitable marketing and social circlejerk. Seriously--write a bot to crawl these issues links and they all point to each other, all stuck on each other. We're watching Vista unfold in real time here. Sure, I can email a few buddies and get this bumped from 7 to 20 upvotes. Meanwhile there's critical stuff with thousands of votes ignored for years so what's the point? I'm not sure what personality type is motivated to dive into this particular flavor of open source mess, but just as soon as @karelz finds a few minutes to tinker with the GitHub to Microsoft BI adaptor I'm sure he'll post a few numbers in support of his favorite bugs. And I were going to donate my time, I can think of a few thousand organizations more needy than the corporation that has the most cash on hand of any entity on Earth. But that's just me. |
@karelz Can I just say that, reading through this thread, there is legitimate criticism here that can easily be addressed. Microsoft employees might consider not being so defensive... you guys created a HUGE mess for the ecosystem. It's your job to sort it out. It's not our fault the team decided to boil the ocean... do you think the Vista team didn't have to deal with disgruntled people? There's a real simple solution. Just say "thanks for your feedback, we'll take it into consideration" and move on. You don't HAVE to respond to every single piece of criticism, but you definitely should not be deleting it, either. |
People star and/or watch repos because they are/were using them or because they know they will need to use them at some point or just because they want to follow the development so there are good reasons for it. People that value their time, lose their attitude and don't waste their time on making stupid assumptions, bragging or trolling and finally expect people to take them seriously. If you don't trust Microsoft and/or their process either give them feedback about it, writing something is always better than nothing or shut it! I actually need this feature because I'm working on a console application and I want to move it to .NET Core and I want to intercept SIGINT when the user exit the application.
thumbs up/down are just reaction to a specific issue, I doubt that Microsoft prioritize their work on the amount of thumbs up, it might be an indication that people need this feature but that's all, it's just another form of feedback.
Have fun. |
@eyalsk, can you use Console.CancelKeyPress? It raises an event for SIGINT and let's you handle it. |
@stephentoub I haven't tried it yet, I'm still digging what it would take for me to port the application. Does everything related to Console.* works on .NET Core? |
On Windows, pretty much all of console works as it does on desktop. On Unix, most of the support works as you'd expect, but some of the more esoteric functionality (e.g. screen buffers) is limited. |
Thinking about some use-cases I have for signals, I want to propose some API calls. @Petermarcu and others, please provide feedback if these calls would cover your use-cases. These are members of a static Signal class. A common use-case is to send a signal to a process to kill or term it:
This call would probably be used in a while loop with Process.WaitForExit. Another interesting use-case is sending a signal to a specific thread to unblock it. Perhaps some native method was invoked on this thread which can be stopped by sending it a specific signal.
This call would probably be used in a while loop with Thread.Join. There are several signals which can be used for user-defined signals (sigusr, real time). As signals are process wide, it may be interesting to have a way of acquiring a signal for 'exclusive' use.
One interesting case is a handler which has an empty body and is used to unblock system calls. This handler may be used by different consumers since it is a no-op.
We need a way to block and unblock signals.
These operations are at the thread level. So perhaps they should be allowed only on specific types of threads (e.g. not on the thread pool). -edited- Adding a handler:
This would keep a list of actions per signal value. When the first action is added, the signalaction would change to execute the handlers. When the last action is removed, the signalaction would revert to the default. As process directed signals may be handled by any unblocked thread, it is important the user realizes a call to AddHandler may cause the action to be executed if another thread has Unblocked it. This is where the AquireSignal comes into play which allows a user to reserve a signal that should not be used by others. Since not all functions can be called from a signal handler, it may make sense to defer the action to the threadpool and block the signal handler until it completes. SignalValue in the above is an enum with names of signals. It has to be taken into account that the numeric values are not fixed. |
@stephentoub , can you take a look? |
Thanks for your thoughts on this, @tmds! It's great to discuss all of the various use cases folks may have, so keep that coming. At the same time, this is a fairly large area, with many intricacies that will impact things, e.g. we can't really reasonably run managed code in a signal handler, as aspects of the runtime that could get involved (e.g. JIT, GC, etc.) almost certainly use functionality that's not signal-safe, nevermind the code in the handler itself, libraries they use, etc. And we need to be concerned about existing functionality that's already using/handling signals in the runtime and other CoreFx libraries, e.g. SIGINT and Console.CancelKeyPress, SIGTERM and polite shutdown, debugger interaction, etc. So, I suggest we split this into multiple pieces:
Getting the results for (1) would be awesome, if someone's interested in tackling that, and I expect that will help with the rest of this. I then suggest we leave (4) aside for a bit and tackle (2) and (3) together: I expect (3) should be fairly straightforward to design, and we could then make things much more concrete by getting that as a manageable chunk designed, reviewed, implemented, and merged. Then with that in place as a basis, along with the intel from (1), I expect it would be very helpful for someone to prototype (4), to help understand what works and what doesn't, what issues we'll hit, etc., and use that along with (1) to drive a design for (4), which can then be reviewed, designed, implemented, and merged. Does that seem reasonable? @tmds, you seem fairly passionate about this, and it's great to see all of the thoughts you've already outlined. Would you want to tackle (1) as a start? |
Isn't it better to call
I can speak for node.js (Node) for now. Sending singnals on Node is as simple as doing something like this:
Works both on Windows and Linux.
This will throw an error on all platforms but can be sent through process.kill(process.pid, "SIGKILL"); This is what the documentation for Node 7.4.0 states:
As far as I can tell all signals are supported but some features may or may not be supported or have different behaviour on Windows for example: SIGWINCH: is delivered when the console has been resized. On Windows, this will only happen on write to the console when the cursor is being moved, or when a readable tty is used in raw mode. Personally I don't think it's correct for a signal to send itself because Signals are related to processes so I don't think it's correct to say You can check the documentation for more information about it here and here. Based on this information I'm thinking that the API should be something like this:
Usage:
Just a thought but we can also have a specific enum for each platform like so:
This will basically be mapped to So there might be an overload method that looks like this:
|
If it's possible to create a non-leaky abstraction, I'd prefer to work with an abstraction and write platform-agnostic code. I'd probably hope for something similar to: public enum Signal
{
Kill,
UnixTerm
} |
@jnm2 Sure but seeing how it's implemented in other platforms where the names are kept then I thought it's a good idea to follow it to some extent. As far as I can tell all of them use names that match the Unix names, I don't mind changing the names to pascal casing as opposed to upper casing and give them more readable names but I still think that the name of the enum should be UnixSignal. :)
p.s. I'm not aware of anything like this in the Java world or more precisely you can't send signals directly with Java, at least without some 3rd-party library that provides it. |
This Java product seems to have influenced Mono. http://www.bmsi.com/java/posix/index.html A bigger issue (and source of future breaking changes) is that the .NET Core team is hopping along with their process and console stuff with little consideration of the cross-platform requirements. You should start bottom up with signals not slap a GitHub kiss-of-death "backlog" button on it. It's a core concept everyone needs to understand and affects your designs today. |
Cross platform is a key aspect of everything new we add. I'm not sure what you're referring to around Process and Console; the only APIs there are ones that already exist in .NET, and such compat is another key aspect. I believe we are starting fresh for signals, which is why I asked for background on use cases, on other platform designs, etc. Let's keep this thread focused on the design and refrain from higher level commentary on processes by which this repo is managed: you've made your opinions clear, they've been noted, and they'll be considered for the future; if you have other suggestions on processes related to the repo, please open a separate issue. Thanks for the link. |
There's already legacy gunk in Console app startup that's going to break future Signals work. The .NET team was alerted to this by Miguel ten years ago. As for cross-platform: you can't tell me with a straight face that Microsoft seriously considered SIGTERM vs SIGINT while planning the development arc of .NET Core's console app functionality. That's why this bug exists. And more importantly why it was then buried and scheduled for consideration sometime in 2025. I'll promise to be nicer if Microsoft promises to be a little less full of crap. And I'm still not sure why you're dragging the "community" into this when the first step should be to talk to the Mono guys down the hall. But you got the obvious wrongheaded design and three Google links instead of typing the search in yourself, so engagement metrics are up. Carry on. |
@stephentoub tacking (1) Sending signals to a process:
Sending signals to a process group:
(note for this to work a process must call setpgid between fork and execve, a process started with the Process class doesn't provide a flag to enable this)
note currently there is no API to retrieve the native thread id: Handling signals:
remove a handler:
ignore signal:
More in depth for go: |
Thanks, @tmds.
I don't think we should use Process here either; if the signature takes an int and the developer already has a Process, all they have to do is pass in p.Id, but if the signatures takes a Process and the developer has an int, they have to use the Process class to get a Process object for that int, which is not cheap. And the implementation is just going to turn around and extract the int Id anyway. I think it's better to keep this function lower-level than System.Diagnostics.Process and keep it entirely out of the abstraction.
What is the benefit of this? We've already discussed how the signals would be handled asynchronously, so it likely wouldn't end up being handled by the target thread anyway. Even if it was, for certain dispositions it'll affect the whole process anyway.
I see. Ok, I can see the value of the struct as you've defined it. It will likely be a bit more expensive, because accessing a property will require a P/Invoke to get the signal number, though it could be cached so that it would only need to be done once.
I would rather get the design ironed out in issues before opening PRs. You're welcome to provide links to branches that include your work, of course, but opening PRs when new APIs haven't been fully reviewed means the PRs will just sit there, and we'll end up with discussions in both issues and on the PR. Thanks, again, for your interest in working on this.
Given everything discussed thus far, I still think the posix functions wrappers approach makes the most sense. Thoughts? If we went that route, then such a struct would just live in that library as well, and the Kill method would accept a SignalNumber struct in addition to the int pid. |
I don't think it will be common to send signals to processes for which you don't have a Process instance. But I understand the interest in avoiding the overhead of the Process class creation for when you don't.
It can be used to unblock the target thread on a blocking syscall. You can set a variable to indicate the thread should stop and then send the signal to the thread to unblock it. The disposition of this signal would be a no-op. It is the posix wrapper for pthread_kill. Since the use case is far less common, maybe we leave it out for now.
Right. As an alternative for the SignalNumber struct, we can also just use an int. Then we are at: namespace System.Posix
{
public static class Signal
{
public static void Send(int pid, int signal, bool sendToGroup);
public static int Hup { get; }
public static int Term { get; }
// ...
public static int RtMin { get; }
public static int RtMax { get; }
// value returned when not present on platform
public static int Unsupported { get; }
}
} |
I'd rename the method to Just my 2c. |
@stephentoub et al, I made a signal sending implementation, as a proof-of-concept. See https://github.com/tmds/Tmds.Posix. I experimented a bit with the error handling. The implementation has two methods for sending signals. public static void SendToProcess(int pid, int signal, bool sendToGroup);
public static NativeError TrySendToProcess(int pid, int signal, bool sendToGroup); The NativeError used here is just wrapping the int errno. It can be turned into something more useful with some extension methods: public static void ThrowOnError(this NativeError error);
public static Error ToError(this NativeError error);
public static string Describe(this NativeError error);
public static bool IsSuccess(this NativeError error); The Error is a platform agnostic representation of the errno (it is the same as the internal Error enum in core). Throw will throw a PosixException which exposes the error message, native and platform-independent error number. |
Good job. However, I'm not sure about this |
@stephentoub @eyalsk @tmds . |
@sillyousu 2.0 feature complete / API freeze was on 4/14. This is something we might potentially fund for next version - 2.1, but it is not yet done deal. |
@karelz any news on whether this is likely to make it to 2.1? Lack of signal handling is a bit of a pain working with .NET Core daemons in mixed environments 😖 |
I though the verdict was that using Mono.Posix was the solution for Unix-specific stuff. https://www.nuget.org/packages/Mono.Posix.NETStandard/1.0.0-beta3 |
@agc93 have you tried Mono.Posix? Is it sufficient? |
Do you know where can I find some example code on using Mono.Posix.NETStandard @dlech ? |
@tjaart - are you looking for any sample code? Or specifically signal handling? For signal handling, you have 2 options:
var sigintRaised = new UnixSignal(Signum.SIGINT);
while (sigintRaised.WaitOne()) {
Console.WriteLine(“Control-C pressed!”);
} Note that it blocks the thread until the signal is raised. See http://docs.go-mono.com/?link=T%3aMono.Unix.UnixSignal for docs. |
Don't know of any examples. I've just used the documentation as a guide. |
@karelz Any progress on this? |
It is up-for-grabs and marked for Future - i.e. no immediate plans from our side at this moment. However, I think there was some work done recently in the area by @tmds or @eerhardt. Also, did you try Mono.Posix as suggested above? Is it not sufficient? |
@karelz Yes, Mono.Posix match the requirements, only asking if the intention of creating System.Posix.Signal is in development or if I can start an implementation for a future PR. |
I wouldn't get too far into an implementation without getting an API at least proposed and on the way to getting approved. Since getting it to an approved state may drastically change the implementation. So I'd suggest just doing prototyping to get to a place to have a proposed API. See https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md for the process. Also, along with proposing a new API, I'd consider what are the advantages of a new API over the existing APIs in Mono.Posix. And alternatively, if the additions could be made to Mono.Posix instead, which would benefit both Mono and .NET Core at the same time. My understanding of the current plan is to not duplicate APIs in Mono.Posix just so they are in the |
@eerhardt If the solution is not implement this in favour of Mono.Posix i think that we can close this. |
It would be my preference to close this as well. I haven't seen any real-world scenarios that aren't supported by the Mono.Posix APIs, and that would justify creating a brand new, competing API. I'm sure Mono would accept PRs to enhance the existing APIs, if necessary. Anyone else have opinions? |
Also in favor of closing. Mono.Posix should be good for generic handling/sending signals. Overview of what is currently possible using .NET Core:
|
Closing in favor of the existing specialized APIs shown directly above by @tmds and for general signal sending and handling with https://www.nuget.org/packages/Mono.Posix.NETStandard/. For signal handling, you have 2 options:
var sigintRaised = new UnixSignal(Signum.SIGINT);
while (sigintRaised.WaitOne()) {
Console.WriteLine(“Control-C pressed!”);
} Note that it blocks the thread until the signal is raised. See http://docs.go-mono.com/?link=T%3aMono.Unix.UnixSignal for docs. |
Mono.Posix doesn't let you send a signal to a process given its process ID. It is, therefore, pretty useless for the purpose of this issue. |
We should not reopen issues which are closed for 2 years. Our plan is to actually lock closed issues after few weeks of being closed and without comments. |
@shravan2x - does the following help? |
@eerhardt From your link, it seems to be |
Signals are a ubiquitous mechanism across Unix systems for interactions between processes and the kernel. The only API we currently have for sending any signal is Process.Kill(), which sends a SIGKILL signal, but to write robust Unix applications (and services) you likely want to be able to both send signals and handle specific signals. The former can be done by a dev using a P/Invoke, but the latter would really require libcoreclr support to do correctly, especially since the runtime itself already hooks certain signals (e.g. a SIGINT signal sent by ctrl-C, which we then subscribe to the runtime for in Console.CancelEventHandler).
The text was updated successfully, but these errors were encountered: