enkessler / childprocess

Cross-platform Ruby library for managing child processes.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Error 6: The handle is invalid

JoshCheek opened this issue · comments

Trying to launch a process, kill it if it times out, kill it if the process that launched it is interrupted. When it dies, it should take its descendants with it. It's working for me on my mac and on Travis (CI for Linux), but not on AppVeyor (CI for Windows). While tweaking different things, I've also seen error 5, "Access is denied" and I've had it just kill the tests without a backtrace when I tried stopping the child process and rescuing any ChildProcess::Errors from invalid handles.

  • I've recreated the issue so that it can be analyzed without the distraction of my gem.
  • It fails on AppVeyor (Windows)
  • It passes on Travis (Linux)

It seems the error occurs when you call stop after having called wait. When I added this test to your suite (screenshot b/c I don't know how to copy/paste through the VM barrier):

screenshot 2016-12-31 01 53 58

It blew up on the line where I called stop in the same way that my tests are:

screenshot 2016-12-31 01 55 40

I'm calling stop because it was leaving orphan processes before. But I'll see if there's not a way to get all my tests passing in both environments.

Okay, got all the tests passing on windows and unix. Note that I do have to explicitly check what system I'm on:

  • In the test to see how to detect whether the process is running.
  • In the implementation to see whether I need to call stop or not (if I don't call it, Unix leaves orphans, if I do call it, Windows blows up, but I do need to call it on Windows when there is an error like an interrupt)

@JoshCheek Thanks for the info! I'll take a look in the next couple of days.

@JoshCheek Okay. As you have already figured out, the problem does seem to stem from your code calling Process#stop after calling Process#wait. Essentially, you are telling the OS to kill a process that doesn't exist anymore and Windows particularly seems to not like that.

Rather than have the extra OS checks and lower level implementation, have you tried using Process#exited? in order to see if you still need to call stop? That should be more consistent across operating systems.

@JoshCheek Did you get a chance to check out Process.exited??

I did try it but I didn't go with it. I don't remember why. Should have come back and updated the issue at that time.

I feel like it didn't work the way I needed it to (I have a vague memory that if I asked before calling #wait, that it would cause #wait to error instead and that I sometimes needed to be able to call it before calling #wait). But that could be a false memory. I seem to also remember reordering the code to where I didn't have the need for it, but I can't say if that's the reason I didn't use it, or if I did that because it wasn't working as expected. I also switched to posix spawn, which I think was a separate thing after the fact, but could have been related. Not super helpful, I know >.<

So...reasons. Got it. ;)

At this point, is there still an issue that you need fixed? If not, feel free to close this Issue. If so, feel free to post another update that will help get you and I on the same page so that we can tackle stuff.

I don't currently have an issue. Hopefully I've left enough breadcrumbs that anyone who hits this later can find and follow.