On Wednesday, February 5, 2014 5:03:37 PM UTC-8, Nikolaus Rath wrote:
>
> Hi Nicola, 
>
> On 02/05/2014 10:52 AM, Nicola Cocchiaro wrote: 
> > Hi Nikolaus, 
> > 
> > Are there timeouts for HTTP requests sent by S3ql? I took a look at the 
> > 2.7 code (backends/common.py), and the http.client.HTTPConnection 
> > constructor calls there (as well as HTTPSConnection ones) don't seem to 
> > specify a timeout, and it's my understanding from the Python docs that 
> > this would mean defaulting to the global default timeout. However the 
> > default timeout for the socket library (which this should fall back to) 
> > is None in the absence of a call to socket.setdefaulttimeout(), meaning 
> > HTTP requests could block indefinitely. Is there a timeout set elsewhere 
> > in code that I haven't been able to find and you can point me to? 
>
> No, S3QL does not set any timeouts explicitly. It will wait until the 
> server closes its side of the TCP connection, or (if the connection is 
> interrupted) until the kernel's TCP stack decides the connection has 
> been lost. 
>  


The reason I originally asked was due to seeing some outbound connections 
not completing but just hanging, until using umount.s3ql would let them 
return with a TimeoutError (no less than 15 minutes later in all cases 
seen). I was not able to dig much deeper at the time, but to experiment 
more I put together a simple patch to add a configurable socket timeout to 
all S3ql tools that may make use of it. I've attached it if you'd like to 
consider it.

Nicola Cocchiaro

-- 
You received this message because you are subscribed to the Google Groups 
"s3ql" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
diff -ru s3ql-2.7/src/s3ql/adm-orig.py s3ql-2.7/src/s3ql/adm.py
--- s3ql-2.7/src/s3ql/adm-orig.py	2013-12-11 02:04:17.000000000 +0000
+++ s3ql-2.7/src/s3ql/adm.py	2014-03-05 23:51:06.006508081 +0000
@@ -23,6 +23,7 @@
 import textwrap
 import time
 import atexit
+import socket
 
 log = logging.getLogger(__name__)
 
@@ -61,6 +62,7 @@
     parser.add_cachedir()
     parser.add_version()
     parser.add_fatal_warnings()
+    parser.add_socket_timeout()
 
     options = parser.parse_args(args)
 
@@ -80,6 +82,10 @@
     if is_mounted(options.storage_url):
         raise QuietError('Can not work on mounted file system.')
 
+    # Set a default socket timeout if required
+    if options.socket_timeout is not None:
+        socket.setdefaulttimeout(options.socket_timeout)
+
     if options.action == 'clear':
         try:
             backend = get_backend(options, plain=True)
diff -ru s3ql-2.7/src/s3ql/fsck-orig.py s3ql-2.7/src/s3ql/fsck.py
--- s3ql-2.7/src/s3ql/fsck-orig.py	2013-12-11 02:04:18.000000000 +0000
+++ s3ql-2.7/src/s3ql/fsck.py	2014-03-05 23:50:53.236750083 +0000
@@ -27,6 +27,7 @@
 import textwrap
 import time
 import atexit
+import socket
 
 log = logging.getLogger(__name__)
 
@@ -1056,6 +1057,7 @@
     parser.add_version()
     parser.add_storage_url()
     parser.add_fatal_warnings()
+    parser.add_socket_timeout()
 
     parser.add_argument("--batch", action="store_true", default=False,
                       help="If user input is required, exit without prompting.")
@@ -1078,6 +1080,10 @@
     if is_mounted(options.storage_url):
         raise QuietError('Can not check mounted file system.')
 
+    # Set a default socket timeout if required
+    if options.socket_timeout is not None:
+        socket.setdefaulttimeout(options.socket_timeout)
+
     try:
         backend = get_backend(options)
     except DanglingStorageURLError as exc:
diff -ru s3ql-2.7/src/s3ql/mkfs-orig.py s3ql-2.7/src/s3ql/mkfs.py
--- s3ql-2.7/src/s3ql/mkfs-orig.py	2013-12-11 02:04:18.000000000 +0000
+++ s3ql-2.7/src/s3ql/mkfs.py	2014-03-05 23:51:24.026166592 +0000
@@ -24,6 +24,7 @@
 import tempfile
 import time
 import atexit
+import socket
 
 log = logging.getLogger(__name__)
 
@@ -40,6 +41,7 @@
     parser.add_version()
     parser.add_storage_url()
     parser.add_fatal_warnings()
+    parser.add_socket_timeout()
 
     parser.add_argument("-L", default='', help="Filesystem label",
                       dest="label", metavar='<name>',)
@@ -94,6 +96,10 @@
         log.warning('Warning: maximum object sizes less than 1 MiB will seriously degrade '
                  'performance.', extra={ 'force_log': True })
 
+    # Set a default socket timeout if required
+    if options.socket_timeout is not None:
+        socket.setdefaulttimeout(options.socket_timeout)
+
     try:
         plain_backend = get_backend(options, plain=True)
         atexit.register(plain_backend.close)
diff -ru s3ql-2.7/src/s3ql/mount-orig.py s3ql-2.7/src/s3ql/mount.py
--- s3ql-2.7/src/s3ql/mount-orig.py	2013-12-11 02:04:18.000000000 +0000
+++ s3ql-2.7/src/s3ql/mount.py	2014-03-05 19:57:57.621599740 +0000
@@ -36,6 +36,7 @@
 import time
 import shutil
 import atexit
+import socket
 
 log = logging.getLogger(__name__)
 
@@ -104,6 +105,10 @@
                         "available file descriptors.", options.max_cache_entries, avail_fd)
             options.max_cache_entries = avail_fd
 
+    # Set a default socket timeout if required
+    if options.socket_timeout is not None:
+        socket.setdefaulttimeout(options.socket_timeout)
+
     if options.profile:
         import cProfile
         import pstats
@@ -509,6 +517,7 @@
     parser.add_version()
     parser.add_storage_url()
     parser.add_fatal_warnings()
+    parser.add_socket_timeout()
 
     parser.add_argument("mountpoint", metavar='<mountpoint>', type=os.path.abspath,
                         help='Where to mount the file system')
diff -ru s3ql-2.7/src/s3ql/parse_args-orig.py s3ql-2.7/src/s3ql/parse_args.py
--- s3ql-2.7/src/s3ql/parse_args-orig.py	2013-12-11 02:04:18.000000000 +0000
+++ s3ql-2.7/src/s3ql/parse_args.py	2014-03-05 20:04:52.363740028 +0000
@@ -176,6 +176,14 @@
                            'it reaches 1 MiB, and at most 5 old log files will be kept. '
                            'Specify ``none`` to disable logging. Default: ``%(default)s``')
 
+    def add_socket_timeout(self, default=None):
+        self.add_argument("--socket-timeout", metavar='<socket-timeout>', default=default,
+                      type=float,
+                      help='Set a default socket timeout (in seconds) which will affect '
+                           'all newly created sockets and will disable the default '
+                           'blocking mode.')
+
+
     def add_fatal_warnings(self):
         # Make all log messages of severity warning or higher raise
         # exceptions. This option is not listed in the --help output and used by

Reply via email to