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

Errno::ECHILD thrown from Process.waitpid, some Process methods #732

Merged
merged 8 commits into from May 27, 2013
Merged
1 change: 1 addition & 0 deletions lib-topaz/bootstrap.rb
Expand Up @@ -11,6 +11,7 @@
load_bootstrap.call("comparable.rb")
load_bootstrap.call("enumerable.rb")
load_bootstrap.call("enumerator.rb")
load_bootstrap.call("errno.rb")
load_bootstrap.call("file.rb")
load_bootstrap.call("fixnum.rb")
load_bootstrap.call("hash.rb")
Expand Down
4 changes: 4 additions & 0 deletions lib-topaz/errno.rb
@@ -0,0 +1,4 @@
module Errno
class ECHILD < SystemCallError
end
end
9 changes: 8 additions & 1 deletion lib-topaz/process.rb
Expand Up @@ -8,8 +8,15 @@ def self.waitpid2(pid = -1)
return [pid, $?]
end

def self.wait2(pid = -1)
waitpid2(pid)
end

def self.waitall
raise NotImplementedError.new("Process.waitall")
result = []
result << wait2 while true
rescue Errno::ECHILD
result
end

class Status
Expand Down
2 changes: 0 additions & 2 deletions spec/tags/core/process/wait2_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/tags/core/process/wait_tags.txt
@@ -1,4 +1,3 @@
fails:Process.wait raises a Errno::ECHILD if there are no child processes
fails:Process.wait waits for any child process if no pid is given
fails:Process.wait waits for a specific child if a pid is given
fails:Process.wait coerces the pid to an Integer
Expand Down
2 changes: 0 additions & 2 deletions spec/tags/core/process/waitall_tags.txt
@@ -1,3 +1 @@
fails:Process.waitall returns an empty array when there are no children
fails:Process.waitall waits for all children
fails:Process.waitall returns an array of pid/status pairs
1 change: 0 additions & 1 deletion topaz.mspec
Expand Up @@ -63,7 +63,6 @@ class MSpecScript
"^#{Rubyspec}/core/process/status/signaled_spec.rb",
"^#{Rubyspec}/core/process/status/success_spec.rb",
"^#{Rubyspec}/core/process/status/termsig_spec.rb",
"^#{Rubyspec}/core/process/wait_spec.rb",
"^#{Rubyspec}/core/file/ctime_spec.rb"
]

Expand Down
15 changes: 15 additions & 0 deletions topaz/error.py
@@ -1,4 +1,5 @@
import os
import errno


class RubyError(Exception):
Expand Down Expand Up @@ -31,3 +32,17 @@ def error_for_oserror(space, exc):
os.strerror(exc.errno),
[space.newint(exc.errno)]
)

_errno_for_oserror_map = {
errno.ECHILD: "ECHILD",
}

def errno_for_oserror(callee, space, exc):
try:
name = _errno_for_oserror_map[exc.errno]
except KeyError:
raise NotImplementedError("no such errno: %s" % exc.errno)
Copy link
Member

Choose a reason for hiding this comment

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

This should probably just raise a normal SystemCallError if we don't know the specific sucblass.

Copy link
Member

Choose a reason for hiding this comment

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

To be honest this whole function should be merged with the other error_for_oserror function.

return space.error(
space.find_const(space.find_const(callee, "Errno"), name),
os.strerror(exc.errno)
)
6 changes: 5 additions & 1 deletion topaz/modules/process.py
Expand Up @@ -4,6 +4,7 @@

from topaz.module import ModuleDef
from topaz.system import IS_WINDOWS
from topaz.error import errno_for_oserror


if IS_WINDOWS:
Expand Down Expand Up @@ -35,7 +36,10 @@ def method_pid(self, space):

@moduledef.function("waitpid", pid="int")
def method_waitpid(self, space, pid=-1):
pid, status = os.waitpid(pid, 0)
try:
pid, status = os.waitpid(pid, 0)
except OSError as e:
raise errno_for_oserror(self, space, e)
status = WEXITSTATUS(status)
w_status = space.send(
space.find_const(self, "Status"),
Expand Down