+class pchild(object):
+ """class pchild(argv, autorespawn=False, chinit=None)
+
+ Represents a persistent child handler process, started as per the
+ standard ashd(7) calling convention. It will be called with the
+ `argv' argument lest, which should be a list (or other iterable)
+ of strings.
+
+ If `autorespawn' is specified as True, the child process will be
+ automatically restarted if a request cannot be successfully sent
+ to it.
+
+ For a description of the `chinit' argument, see `stdfork'.
+
+ When this child handler should be disposed of, care should be
+ taken to call the close() method to release its socket and let it
+ exit. This class also implements the resource-manager interface,
+ so that it can be used in `with' statements.
+ """
+
+ def __init__(self, argv, autorespawn = False, chinit = None):
+ self.argv = argv
+ self.chinit = chinit
+ self.fd = -1
+ self.respawn = autorespawn
+ self.spawn()
+
+ def spawn(self):
+ """Start the child handler, or restart it if it is already
+ running. You should not have to call this method manually
+ unless you explicitly want to manage the process' lifecycle.
+ """
+ self.close()
+ self.fd = stdfork(self.argv, self.chinit)
+
+ def close(self):
+ """Close this child handler's socket. For normal child
+ handlers, this will make the program terminate normally.
+ """
+ if self.fd >= 0:
+ os.close(self.fd)
+ self.fd = -1
+
+ def __del__(self):
+ self.close()
+
+ def passreq(self, req):
+ """Pass the specified request (which should be an instance of
+ the ashd.proto.req class) to this child handler. If the child
+ handler fails for some reason, and `autorespawn' was specified
+ as True when creating this handler, one attempt will be made
+ to restart it.
+
+ Note: You still need to close the request normally.
+
+ This method may raise an OSError if the request fails and
+ autorespawning was either not requested, or if the
+ autorespawning fails.
+ """
+ try:
+ proto.sendreq(self.fd, req)
+ except OSError:
+ if self.respawn:
+ self.spawn()
+ proto.sendreq(self.fd, req)
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *excinfo):
+ self.close()
+ return False
+