Timeout curl in the event Apache (PLC side) opens the XMLRPC session, but returns...
authorFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Tue, 17 Jun 2008 18:47:22 +0000 (18:47 +0000)
committerFaiyaz Ahmed <faiyaza@cs.princeton.edu>
Tue, 17 Jun 2008 18:47:22 +0000 (18:47 +0000)
conf_files.py
curlwrapper.py
plcapi.py
safexmlrpc.py

index c5d5924..24d5509 100644 (file)
@@ -10,7 +10,7 @@ import threading
 import curlwrapper
 import logger
 import tools
-
+import xmlrpclib
 
 class conf_files:
     def __init__(self, config, noscripts=False):
@@ -52,7 +52,7 @@ class conf_files:
         url = 'https://%s/%s' % (self.config.PLC_BOOT_HOST, cf_rec['source'])
         try:
             contents = curlwrapper.retrieve(url, self.config.cacert)
-        except curlwrapper.CurlException:
+        except xmlrpclib.ProtocolError,e:
             logger.log('conf_files: failed to retrieve %s from %s, skipping' % (dest, url))
             return
         if not cf_rec['always_update'] and sha.new(contents).digest() == self.checksum(dest):
index e259578..4aa634d 100644 (file)
@@ -1,18 +1,36 @@
-from subprocess import PIPE, Popen
+# $Id$
 
+from subprocess import PIPE, Popen
+from select import select
+# raise xmplrpclib.ProtocolError
+import xmlrpclib
+import signal
+import os
+import logger
 
-class CurlException(Exception): pass
+class Sopen(Popen):
+    def kill(self, signal = signal.SIGTERM):
+        os.kill(self.pid, signal)
 
-def retrieve(url, cacert=None, postdata=None, timeout=300):
+def retrieve(url, cacert=None, postdata=None, timeout=90):
     options = ('/usr/bin/curl', '--fail', '--silent')
     if cacert: options += ('--cacert', cacert)
     if postdata: options += ('--data', '@-')
-    if timeout: options += ('--max-time', str(timeout))
-    p = Popen(options + (url,), stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+    if timeout: 
+        options += ('--max-time', str(timeout))
+        options += ('--connect-timeout', str(timeout))
+    p = Sopen(options + (url,), stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
     if postdata: p.stdin.write(postdata)
     p.stdin.close()
+    sout, sin, serr = select([p.stdout,p.stderr],[],[], timeout)
+    if len(sout) == 0 and len(sin) == 0 and len(serr) == 0: 
+        logger.verbose("curlwrapper: timed out after %s" % timeout)
+        p.kill(signal.SIGKILL) 
     data = p.stdout.read()
     err = p.stderr.read()
     rc = p.wait()
-    if rc != 0: raise CurlException(err)
-    else: return data
+    if rc != 0: 
+        # when this triggers, the error sometimes doesn't get printed
+        raise xmlrpclib.ProtocolError(url, rc, err, postdata)
+    else: 
+        return data
index 4da9e48..759207e 100644 (file)
--- a/plcapi.py
+++ b/plcapi.py
@@ -1,3 +1,5 @@
+# $Id$
+
 import safexmlrpc
 import hmac, sha
 
@@ -15,7 +17,7 @@ class PLCAPI:
     the new session-based method.
     """
 
-    def __init__(self, uri, cacert, auth, timeout = 300, **kwds):
+    def __init__(self, uri, cacert, auth, timeout = 90, **kwds):
         if isinstance(auth, (tuple, list)):
             (self.node_id, self.key) = auth
             self.session = None
index 71799ff..5346b3c 100644 (file)
@@ -1,26 +1,30 @@
+# $Id: safexmlrpc.py 9491 2008-05-28 15:49:13Z thierry $
+
 """Leverage curl to make XMLRPC requests that check the server's credentials."""
 
-import curlwrapper
 import xmlrpclib
 
+import curlwrapper
+
+
+class CertificateCheckingSafeTransport (xmlrpclib.Transport):
 
-class CertificateCheckingSafeTransport(xmlrpclib.Transport):
     def __init__(self, cacert, timeout):
         self.cacert = cacert
         self.timeout = timeout
 
     def request(self, host, handler, request_body, verbose=0):
         self.verbose = verbose
-        try:
-            contents = curlwrapper.retrieve('https://%s%s' % (host, handler),
-                                            cacert = self.cacert,
-                                            postdata = request_body,
-                                            timeout = self.timeout)
-            return xmlrpclib.loads(contents)[0]
-        except curlwrapper.CurlException, e:
-            raise xmlrpclib.ProtocolError(host + handler, -1, str(e), '')
+        url='https://%s%s' % (host, handler)
+        # this might raise an xmlrpclib.Protocolerror exception
+        contents = curlwrapper.retrieve(url,
+                                        cacert = self.cacert,
+                                        postdata = request_body,
+                                        timeout = self.timeout)
+        return xmlrpclib.loads(contents)[0]
 
 class ServerProxy(xmlrpclib.ServerProxy):
+
     def __init__(self, uri, cacert, timeout = 300, **kwds):
         xmlrpclib.ServerProxy.__init__(self, uri,
                                        CertificateCheckingSafeTransport(cacert, timeout),