This commit is contained in:
@@ -86,8 +86,8 @@ The wire protocol is to pickle the Request class in this file. The
|
|||||||
request class is basically an action and a map of parameters'
|
request class is basically an action and a map of parameters'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
from cPickle import dumps, loads
|
from cPickle import dumps, loads
|
||||||
|
import os
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -182,6 +182,8 @@ class Request(object):
|
|||||||
|
|
||||||
def _read_lp_hunk(stream):
|
def _read_lp_hunk(stream):
|
||||||
len_bytes = stream.read(4)
|
len_bytes = stream.read(4)
|
||||||
|
if len_bytes == '':
|
||||||
|
raise EOFError("No more data to read from %s" % stream)
|
||||||
length = struct.unpack('I', len_bytes)[0]
|
length = struct.unpack('I', len_bytes)[0]
|
||||||
body = stream.read(length)
|
body = stream.read(length)
|
||||||
return body
|
return body
|
||||||
@@ -247,6 +249,7 @@ def _unmunge_attr_name(name):
|
|||||||
name = name[len('_Proxy'):]
|
name = name[len('_Proxy'):]
|
||||||
if(name.startswith('_ObjectProxy')):
|
if(name.startswith('_ObjectProxy')):
|
||||||
name = name[len('_ObjectProxy'):]
|
name = name[len('_ObjectProxy'):]
|
||||||
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
class ChildProcess(object):
|
class ChildProcess(object):
|
||||||
@@ -282,6 +285,9 @@ class ChildProcess(object):
|
|||||||
|
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
self._in.close()
|
||||||
|
|
||||||
|
|
||||||
class Proxy(object):
|
class Proxy(object):
|
||||||
"""\
|
"""\
|
||||||
@@ -320,7 +326,10 @@ not supported, so you have to know what has been exported.
|
|||||||
request = Request('del', {'id':dead_object})
|
request = Request('del', {'id':dead_object})
|
||||||
|
|
||||||
my_cp.make_request(request)
|
my_cp.make_request(request)
|
||||||
|
try:
|
||||||
_dead_list.remove(dead_object)
|
_dead_list.remove(dead_object)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
# Pass all public attributes across to find out if it is
|
# Pass all public attributes across to find out if it is
|
||||||
# callable or a simple attribute.
|
# callable or a simple attribute.
|
||||||
@@ -423,6 +432,11 @@ not need to deal with this class directly."""
|
|||||||
|
|
||||||
|
|
||||||
def proxied_type(self):
|
def proxied_type(self):
|
||||||
|
""" Returns the type of the object in the child process.
|
||||||
|
|
||||||
|
Calling type(obj) on a saranwrapped object will always return
|
||||||
|
<class saranwrap.ObjectProxy>, so this is a way to get at the
|
||||||
|
'real' type value."""
|
||||||
if type(self) is not ObjectProxy:
|
if type(self) is not ObjectProxy:
|
||||||
return type(self)
|
return type(self)
|
||||||
|
|
||||||
@@ -431,6 +445,14 @@ def proxied_type(self):
|
|||||||
request = Request('type', {'id':my_id})
|
request = Request('type', {'id':my_id})
|
||||||
return my_cp.make_request(request)
|
return my_cp.make_request(request)
|
||||||
|
|
||||||
|
|
||||||
|
def getpid(self):
|
||||||
|
""" Returns the pid of the child process. The argument should be
|
||||||
|
a saranwrapped object."""
|
||||||
|
my_cp = self.__local_dict['_cp']
|
||||||
|
return my_cp._in.getpid()
|
||||||
|
|
||||||
|
|
||||||
class CallableProxy(object):
|
class CallableProxy(object):
|
||||||
"""\
|
"""\
|
||||||
@class CallableProxy
|
@class CallableProxy
|
||||||
@@ -527,7 +549,11 @@ when the id is None."""
|
|||||||
_log("del %s from %s" % (id, self._objects))
|
_log("del %s from %s" % (id, self._objects))
|
||||||
|
|
||||||
# *TODO what does __del__ actually return?
|
# *TODO what does __del__ actually return?
|
||||||
|
try:
|
||||||
del self._objects[id]
|
del self._objects[id]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def handle_type(self, obj, req):
|
def handle_type(self, obj, req):
|
||||||
@@ -547,7 +573,10 @@ when the id is None."""
|
|||||||
try:
|
try:
|
||||||
str_ = _read_lp_hunk(self._in)
|
str_ = _read_lp_hunk(self._in)
|
||||||
except EOFError:
|
except EOFError:
|
||||||
sys.exit(0) # normal exit
|
if _g_debug_mode:
|
||||||
|
_log("Exiting normally")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
request = loads(str_)
|
request = loads(str_)
|
||||||
_log("request: %s (%s)" % (request, self._objects))
|
_log("request: %s (%s)" % (request, self._objects))
|
||||||
req = request
|
req = request
|
||||||
|
@@ -338,6 +338,13 @@ sys_path = sys.path""")
|
|||||||
'random' in obj_proxy.get_dict(),
|
'random' in obj_proxy.get_dict(),
|
||||||
'Coroutine in saranwrapped object did not run')
|
'Coroutine in saranwrapped object did not run')
|
||||||
|
|
||||||
|
def test_child_process_death(self):
|
||||||
|
prox = saranwrap.wrap({})
|
||||||
|
pid = saranwrap.getpid(prox)
|
||||||
|
self.assertEqual(os.kill(pid, 0), None) # assert that the process is running
|
||||||
|
del prox # removing all references to the proxy should kill the child process
|
||||||
|
self.assertRaises(OSError, os.kill, pid, 0) # raises OSError if pid doesn't exist
|
||||||
|
|
||||||
def test_detection_of_server_crash(self):
|
def test_detection_of_server_crash(self):
|
||||||
# make the server crash here
|
# make the server crash here
|
||||||
pass
|
pass
|
||||||
|
Reference in New Issue
Block a user