Partial Fix Issue 16615 - convert os pid to std.process Pid#5086
Partial Fix Issue 16615 - convert os pid to std.process Pid#5086dlang-bot merged 1 commit intodlang:masterfrom
Conversation
|
|
While this is a nice convenience function, this does not address the primary complaint of the bug report: an inability to easily get the pid of a child process. Please change your commit message to |
| { | ||
| version (Windows) TestScript prog = "exit %~1"; | ||
| else version (Posix) TestScript prog = "exit $1"; | ||
| auto pid = spawnProcess([prog.path, "10"]); |
There was a problem hiding this comment.
This is racy - by the time you issue kill the process may already exit normally. An infinite loop would be a better choice then "exit $1"
std/process.d
Outdated
| _processHandle = new Pid(pid, _handle); | ||
| } | ||
|
|
||
| return _processHandle; |
There was a problem hiding this comment.
Most functions of this module will throw on error, I suggest to do the same here.
1486096 to
91ce00d
Compare
91ce00d to
560e2c8
Compare
560e2c8 to
0ee3059
Compare
| version (Windows) | ||
| { | ||
| /** | ||
| A simple factory that returns a $(LREF Pid) handle when provided with a |
There was a problem hiding this comment.
LREF is deprecated, please use REF e.g. $(REF Pid, std, process).
There was a problem hiding this comment.
That would be new to me.
LREF = local reference (within the module), only XREF was deprecated.
std/process.d
Outdated
| A simple factory that returns a $(LREF Pid) handle when provided with a | ||
| global `pid`. This handle can be used to kill processes that haven't been | ||
| spawned by this process. | ||
| `Note:` this does not check if the provided `pid` is valid and corresponds |
There was a problem hiding this comment.
Note should not be in code font.
|
|
||
| (Windows specific) Throws: | ||
| $(LREF ProcessException) on failure. | ||
| */ |
There was a problem hiding this comment.
FYI we currently only generate documentation on Posix, so this doc won't appear anywhere. At some point we should get things going by running wine to build windows dox...
std/process.d
Outdated
| pid = a process id | ||
|
|
||
| Returns: an instance to a `Pid` that corresponds to the pid within the | ||
| operating system, or, on Windows, throws `ProcessException` if opening the |
There was a problem hiding this comment.
The info about throwing should be in a separate section:
Throws: this and that and the other.There was a problem hiding this comment.
Removed the throws part all together since it is Windows specific.
0ee3059 to
44fc785
Compare
44fc785 to
71ca4c5
Compare
|
|
||
| @system unittest // Pid.fromSystemPid() | ||
| { | ||
| version (Windows) TestScript prog = "do { timeout 1 } while (1)"; |
There was a problem hiding this comment.
What the heck is this syntax? It's definitely not .cmd syntax. Is this a broken test?
There was a problem hiding this comment.
It's powershell syntax
There was a problem hiding this comment.
Well, it's not being executed as a PowerShell script. Look at the implementation of TestScript. The string is saved to a .cmd file. In addition to that, I don't think you can just CreateProcess / spawnProcess a .cmd etc. file on Windows. Windows does not have shebangs, associations (incl. .cmd) are handled by userspace (the shell) in a layer above CreateProcess, so you must spawn the command interpreter explicitly.
There was a problem hiding this comment.
In addition to fixing the script, you need to find why your test was broken (in that it allowed a broken script to work and pass the test).
There was a problem hiding this comment.
Well, it's not being executed as a PowerShell script. Look at the implementation of TestScript. The string is saved to a .cmd file. [..]
I have missed that. I just assumed that if the syntax was invalid, auto tester would complain about it.
In addition to fixing the script, you need to find why your test was broken (in that it allowed a broken script to work and pass the test).
Again, I just assumed everything was ok since the tester did not complain about it.
Any suggestions on how to approach the issue and find out why the tester is not complaining?
There was a problem hiding this comment.
Any suggestions on how to approach the issue and find out why the tester is not complaining?
You need to find why your test is broken. You might be missing a check which ensures that everything has gone as expected. If you need more time for this, I suggest we revert the PR for now.
There was a problem hiding this comment.
Try inserting Thread.sleep(1.seconds) before the kill. I'm guessing your test is killing the process before the OS figures out the test script is invalid, in which case it's at least a race condition.
There was a problem hiding this comment.
Try inserting Thread.sleep(1.seconds) before the kill. I'm guessing your test is killing the process before the OS figures out the test script is invalid, in which case it's at least a race condition.
Great observation! I totally missed that this could happen.
|
|
||
| Throws: $(LREF ProcessException) if opening the process failed; this is | ||
| Windows specific. | ||
| */ |
There was a problem hiding this comment.
Do not have different documentation blocks for different platforms. Most users will never see the Windows one. Instead, have a look at version(StdDDoc).
There was a problem hiding this comment.
(or just move the version blocks from outside the function body to inside it, so there's only one declaration)
|
|
||
| Throws: $(LREF ProcessException) if opening the process failed; this is | ||
| Windows specific. | ||
| */ |
There was a problem hiding this comment.
This, or the wait documentation, should mention that wait-ing on a Pid that does not belong to a child (i.e. not created by spawnProcess etc.) is invalid and is not going to work.
There was a problem hiding this comment.
Actually, it seems like there's more to it - currently wait uses asserts to verify the validity of the Pid. If non-child PIDs becomes part of its API, I think those checks need to be made explicit.
There was a problem hiding this comment.
yah that would need to change if we allow non-child pids
|
@andralex Please ping me or Steven or Lars if you need something reviewed regarding std.file or std.process. |
|
So, question: do we actually need this in Phobos? It is certainly a simple enough addition, but: std.process.Pid was created not to encapsulate the PID of any process, but only child processes created by Another question is where do we want to draw the line for general process management. Killing arbitrary processes is the immediate benefit of this change. However, do we also want to have things such as process enumeration, renicing, reading/writing process memory etc.? |
I think we should have this in Phobos, as, imho, this expands the functionality of
I think
On the top of my head, probably only wait and anonymous pipes shouldn't be allowed, since these depend on process relationship. Everything else, imo, should work; we are a systems programming language after all. |
|
@CyberShadow what do you think? |
I don't think that argument makes sense (you can say it about a lot of useless or under-designed proposals); otherwise I can review a follow-up PR, but personally I would like more opinions on whether this functionality is necessary in Phobos. As I see it allowing Pid to represent non-child processes is shoe-horning functionality into it it was never meant to have, with the |
|
Few questions: So now we have Is the call Do other useful functions of Thanks. |
Right now there is an
AFAIU, only |
|
So that puts as at 50/50. Assuming we add more operations on pids, are the majority of those likely to work uniformly for child and non-child processes? If so, adding is good. Are the majority of those likely to NOT work the same for child and non-child processes? Then let's not add. Is there a possibility to fill _handle appropriately on non-child processes? (My cringe: |
I think we need some concrete proposals of what more could be added, and I can't think of any that would belong in Phobos - as I wrote above: "However, do we also want to have things such as process enumeration, renicing, reading/writing process memory etc.?"
Actually it looks like I misread the patch - the added function does fill it, as a handle is needed to kill a process, however for doing so it adds an optional parameter (
|
|
Especially considering the problem with |
|
We have discussed this kind of change before. Killing a pid with the OS API is pretty simple, we could probably wrap that into a single function. The std.process API generally is for creating processes and handling the output/results. When you tack on managing processes that you didn't create, it's almost a separate API. It would belong in std.process, but not in the existing Pid type. Things that you can do with a process id should dictate where our OS-agnostic API should go. We can get pretty far into the weeds on Windows, but Unix capabilties are pretty straightforward (if you don't count A very simple addition would just be a kill function that does the right thing depending on OS. Maybe |
Was about to point out the same. Then why was the revert pulled before this concluded? A larger point - how can we reduce the churn? This whole discussion ideally would have taken place in the issue. |
Because it's obvious there are several non-trivial issues here, the implementation needs improvement anyway, and more time is needed to settle them.
Sorry about that - I haven't seen the original issue or the PR when it was created. I've subscribed to all PRs/issues after DConf but anything that happened before then wasn't on my radar. |
Just speaking for myself -- I haven't had tons of time to read through all the bug reports, so I have lost track of which ones would be good for me to review. Also my list of unread emails from github is hovering over 4000. I just happened to click on this one when it was brought to the top in a few spare minutes I had. The best advice is if there is a section of the runtime/library that is pertinent to a particular person, ping that person either via github in the PR or via bugzilla by subscribing them to that bug. Otherwise, sometimes life gets in the way, and that person may miss it until later. I personally don't have a lot of traffic from bugzilla, so I would see that more likely, and anything that comes from github goes into a bucket on my email except if it has @schveiguy in it, then it goes in my inbox. |
(Also, I proposed the revert specifically after I've re-read the patch, as I think the actual solution was not better than what I thought it was, and it made me realize additional problems with the proposal.) |
Same here. OT: Shortly after DConf, I realized that my morning and evening routine consisted of at least half an hour of Reddit/HN (mainly reading stuff for the sake of it), and I noticed an opportunity for optimization: I've subscribed to all GitHub and Bugzilla notifications (sending those to a separate label) and replaced part of my Reddit time with looking through what accumulated there. Gmail's interface makes it very easy to blaze through threads that are not relevant, so picking out threads relevant to you (or where you can contribute something like triaging a low-effort bug report or bisecting a regression) becomes easy as well. Hopefully I can keep up this habit going forwards, and of course there is the temporary problem that situations like this happen where something shows up on your radar only after it's been merged. |
There is time until the next release.
Could you please get into those? |
I did, and barring additional arguments my conclusion so far is that this is not something that should be in Phobos. See also Steven's reply on the PR - we could have a |
I think the |
|
@CyberShadow could you please suggest a step forward for https://issues.dlang.org/show_bug.cgi?id=16615? Thanks. |
|
WONTFIX. Although it might not be obvious, killing a process is inherently a very platform specific operation. There is and cannot be an obviously correct way to do it on both platforms (Windows and POSIX), because the two platforms manage processes in different way. Windows does not have signals; POSIX does not allow specifying exit codes; and reparenting is done differently on both. Furthermore, the example use case presented in the issue (killing a process tree) is not possible to correctly implement with just |
|
@CyberShadow OK, please put WONTFIX on it with explanation. |
|
Done |
|
IMO, it's OK to add a function to return the OS pid from a Pid object in Phobos. However, going the other way is a bad idea, for the reasons discussed above. Writing a task manager in D implies knowledge of OS-specific implementation details, and due to differences in Windows vs. Posix, I don't think there is any platform-agnostic way to do this. I.e., I don't think this should be used as a reason for allowing arbitrary conversion of OS pids to |
|
Thanks to all! |
I was thinking more along the lines of Even that simple wrapper may be more fluff than substance, as the C functions are pretty straightforward. |
Yeah but
You mean from Task Manager? |
|
Haha, @CyberShadow has a good point, |
|
I mean do the thing that people do on that os. Yes sigterm on unix, task manager closing (or force closing) on windows. Maybe a bool flag for force closing which switches to sigkill and force close. |
|
How do you propose to implement non-force-closing on Windows? |
|
Not sure. I searched online for a mechanism but can't find it. |
The issue on bugzilla states that we are currently missing the functionality of converting a pid to a std.process Pid in order to be able to use the kill function, if someone were to implement a task manager for example.