Bug 57214 - SyncEvolution blocks when the server misbehaves
Summary: SyncEvolution blocks when the server misbehaves
Status: RESOLVED MOVED
Alias: None
Product: SyncEvolution
Classification: Unclassified
Component: SyncEvolution (show other bugs)
Version: 1.3
Hardware: Other All
: medium minor
Assignee: SyncEvolution Community
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-11-17 02:21 UTC by Tobias Mueller
Modified: 2018-10-13 12:45 UTC (History)
1 user (show)

See Also:
i915 platform:
i915 features:


Attachments

Description Tobias Mueller 2012-11-17 02:21:27 UTC
I just realised, while debugging my auth problems from bug 56240 that SyncEvolution can't be interrupted if the server misbehaves.

I my case, I tried to set up a simple digest auth server like so:

 1) pip install  -E /tmp/cyclone -e git+https://github.com/fiorix/cyclone.git/#egg=cyclone
 2) apply the following diff, i.e.
    cd /tmp/cyclone/src/cyclone/; patch -p1 <<EOF

diff --git a/demos/digest_auth/authdemo.py b/demos/digest_auth/authdemo.py
index 020e6ef..e89561a 100755
--- a/demos/digest_auth/authdemo.py
+++ b/demos/digest_auth/authdemo.py
@@ -31,7 +31,7 @@ from twisted.internet import reactor
 class Application(cyclone.web.Application):
     def __init__(self):
         handlers = [
-            (r"/", MainHandler),
+            (r".*$", MainHandler),
         ]
         settings = dict(
             cookie_secret="32oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
@@ -40,8 +40,9 @@ class Application(cyclone.web.Application):
         )
         cyclone.web.Application.__init__(self, handlers, **settings)
 
-
 class MainHandler(digest.DigestAuthMixin, cyclone.web.RequestHandler):
+    SUPPORTED_METHODS = cyclone.web.RequestHandler.SUPPORTED_METHODS + ('PROPFIND',)
+    
     def passwordz(username):
         creds = {
                 'auth_username': 'test',

EOF


 3) run the authdemo.py: /tmp/cyclone/bin/python /tmp/cyclone/src/cyclone/demos/digest_auth/authdemo.py

 4) Have the setup routine from bug 56263 comment #0 run with URL="http://localhost:8888/foo/bar"

 5) then run syncevolution --daemon=no  target-config@radicale cards1
 

The server should crash like this: 
 

$ ./authdemo.py 2012-11-17 02:20:22+0100 [-] Log opened.
2012-11-17 02:20:22+0100 [-] Application starting on 8889
2012-11-17 02:20:22+0100 [-] Starting factory <__main__.Application instance at 0x1464b90>
2012-11-17 02:20:23+0100 [HTTPConnection,0,127.0.0.1] 401 GET /foo/bar/cardss (127.0.0.1) 0.78ms
2012-11-17 02:20:25+0100 [HTTPConnection,1,127.0.0.1] 401 GET /foo/bar/c (127.0.0.1) 0.38ms
2012-11-17 02:20:28+0100 [HTTPConnection,2,127.0.0.1] Unhandled error in Deferred:
2012-11-17 02:20:28+0100 [HTTPConnection,2,127.0.0.1] Unhandled Error
	Traceback (most recent call last):
	  File "/tmp/cyclone2/src/cyclone/cyclone/httpserver.py", line 185, in _on_request_body
	    self.request_callback(self._request)
	  File "/tmp/cyclone2/src/cyclone/cyclone/web.py", line 1358, in __call__
	    handler._execute(transforms, *args, **kwargs)
	  File "/tmp/cyclone2/src/cyclone/cyclone/web.py", line 958, in _execute
	    callbackArgs=(args, kwargs))
	  File "/tmp/cyclone2/lib/python2.7/site-packages/twisted/internet/defer.py", line 290, in addCallbacks
	    self._runCallbacks()
	--- <exception caught here> ---
	  File "/tmp/cyclone2/lib/python2.7/site-packages/twisted/internet/defer.py", line 551, in _runCallbacks
	    current.result = callback(current.result, *args, **kw)
	  File "/tmp/cyclone2/src/cyclone/cyclone/web.py", line 967, in _execute_handler
	    function = getattr(self, self.request.method.lower())
	exceptions.AttributeError: 'MainHandler' object has no attribute 'propfind'
	



And syncevolution blocks, i.e. SIGINT (Ctrl+C) doesn't help it to exit. I would have expected to be able to press Ctrl+C to make it return at some stage.


(gdb) bt
#0  0x000000396d0e8b84 in __GI___poll (fds=0x7fffffffa1d0, nfds=1, timeout=300000)
    at ../sysdeps/unix/sysv/linux/poll.c:83
#1  0x00007ffff5f8ce2f in ?? () from /lib64/libneon.so.27
#2  0x00007ffff5f8d0df in ?? () from /lib64/libneon.so.27
#3  0x00007ffff5f8d26b in ?? () from /lib64/libneon.so.27
#4  0x00007ffff5f8dc54 in ne_sock_readline () from /lib64/libneon.so.27
#5  0x00007ffff5f8650f in ?? () from /lib64/libneon.so.27
#6  0x00007ffff5f86c15 in ne_begin_request () from /lib64/libneon.so.27
#7  0x00007ffff5f8630d in ne_request_dispatch () from /lib64/libneon.so.27
#8  0x00007ffff5f949ed in ?? () from /lib64/libneon.so.27
#9  0x00007ffff624e194 in SyncEvo::Neon::Session::propfindURI(std::string const&, int, ne_propname const*, boost::function<void (SyncEvo::Neon::URI const&, ne_prop_result_set_s const*)> const&, SyncEvo::Timespec const&) (this=0x6e2bd0, path="/foo/barmuelli/cards/", depth=1, props=
    0x7ffff64b1ec0, callback=..., deadline=...) at src/backends/webdav/NeonCXX.cpp:422
Python Exception <type 'exceptions.IndexError'> list index out of range: 
#10 0x00007ffff62316fc in SyncEvo::WebDAVSource::listAllItems (this=0x6d9c20, revisions=
    std::map with 0 elements) at src/backends/webdav/WebDAVSource.cpp:1305
#11 0x00007ffff623e2d5 in SyncEvo::WebDAVSource::isEmpty (this=0x6d9c20)
    at src/backends/webdav/WebDAVSource.cpp:1138
#12 0x00000038b58d17f8 in boost::function0<bool>::operator() (this=<optimized out>)
    at /usr/include/boost/function/function_template.hpp:760
#13 0x00000038b58bfeb1 in SyncEvo::SyncContext::getConfigXML (this=0x6900e0, xml=
    "<?xml version=\"1.0\"?>\n<!-- SYNTHESIS SYNCML CLIENT Version 3.2 Configuration file -->\n\n<sysync_config version=\"1.0\">\n\n  <configvar name=\"logpath\" value=\"$(defout_path)\"/>\n\n  <!-- this string is output"..., configname=...) at src/syncevo/SyncContext.cpp:2527
#14 0x00000038b58bb8a9 in SyncEvo::SyncContext::initEngine (this=this@entry=0x6900e0, 
    logXML=logXML@entry=true) at src/syncevo/SyncContext.cpp:2796
---Type <return> to continue, or q <return> to quit---




FTR: Cyclone is not capable of doing digest auth in a manner that is reliably testable (cf. https://github.com/fiorix/cyclone/issues/72), so don't bother looking into that as lightweight, fire and forget solution
Comment 1 Patrick Ohly 2012-11-17 16:50:41 UTC
(In reply to comment #0)
> I just realised, while debugging my auth problems from bug 56240 that
> SyncEvolution can't be interrupted if the server misbehaves.
> 
> I my case, I tried to set up a simple digest auth server like so:
> 
>  1) pip install  -E /tmp/cyclone -e
> git+https://github.com/fiorix/cyclone.git/#egg=cyclone
>  2) apply the following diff, i.e.
>     cd /tmp/cyclone/src/cyclone/; patch -p1 <<EOF
> 
> diff --git a/demos/digest_auth/authdemo.py b/demos/digest_auth/authdemo.py
> index 020e6ef..e89561a 100755
> --- a/demos/digest_auth/authdemo.py
> +++ b/demos/digest_auth/authdemo.py
> @@ -31,7 +31,7 @@ from twisted.internet import reactor
>  class Application(cyclone.web.Application):
>      def __init__(self):
>          handlers = [
> -            (r"/", MainHandler),
> +            (r".*$", MainHandler),
>          ]
>          settings = dict(
>              cookie_secret="32oETzKXQAGaYdkL5gEmGeJJFuYh7EQnp2XdTP1o/Vo=",
> @@ -40,8 +40,9 @@ class Application(cyclone.web.Application):
>          )
>          cyclone.web.Application.__init__(self, handlers, **settings)
>  
> -
>  class MainHandler(digest.DigestAuthMixin, cyclone.web.RequestHandler):
> +    SUPPORTED_METHODS = cyclone.web.RequestHandler.SUPPORTED_METHODS +
> ('PROPFIND',)
> +    
>      def passwordz(username):
>          creds = {
>                  'auth_username': 'test',
> 
> EOF
> 
> 
>  3) run the authdemo.py: /tmp/cyclone/bin/python
> /tmp/cyclone/src/cyclone/demos/digest_auth/authdemo.py
> 
>  4) Have the setup routine from bug 56263 comment #0 run with
> URL="http://localhost:8888/foo/bar"
> 
>  5) then run syncevolution --daemon=no  target-config@radicale cards1
>  
> 
> The server should crash like this: 
>  
> 
> $ ./authdemo.py 2012-11-17 02:20:22+0100 [-] Log opened.
> 2012-11-17 02:20:22+0100 [-] Application starting on 8889
> 2012-11-17 02:20:22+0100 [-] Starting factory <__main__.Application instance
> at 0x1464b90>
> 2012-11-17 02:20:23+0100 [HTTPConnection,0,127.0.0.1] 401 GET
> /foo/bar/cardss (127.0.0.1) 0.78ms
> 2012-11-17 02:20:25+0100 [HTTPConnection,1,127.0.0.1] 401 GET /foo/bar/c
> (127.0.0.1) 0.38ms
> 2012-11-17 02:20:28+0100 [HTTPConnection,2,127.0.0.1] Unhandled error in
> Deferred:
> 2012-11-17 02:20:28+0100 [HTTPConnection,2,127.0.0.1] Unhandled Error
> 	Traceback (most recent call last):
> 	  File "/tmp/cyclone2/src/cyclone/cyclone/httpserver.py", line 185, in
> _on_request_body
> 	    self.request_callback(self._request)
> 	  File "/tmp/cyclone2/src/cyclone/cyclone/web.py", line 1358, in __call__
> 	    handler._execute(transforms, *args, **kwargs)
> 	  File "/tmp/cyclone2/src/cyclone/cyclone/web.py", line 958, in _execute
> 	    callbackArgs=(args, kwargs))
> 	  File
> "/tmp/cyclone2/lib/python2.7/site-packages/twisted/internet/defer.py", line
> 290, in addCallbacks
> 	    self._runCallbacks()
> 	--- <exception caught here> ---
> 	  File
> "/tmp/cyclone2/lib/python2.7/site-packages/twisted/internet/defer.py", line
> 551, in _runCallbacks
> 	    current.result = callback(current.result, *args, **kw)
> 	  File "/tmp/cyclone2/src/cyclone/cyclone/web.py", line 967, in
> _execute_handler
> 	    function = getattr(self, self.request.method.lower())
> 	exceptions.AttributeError: 'MainHandler' object has no attribute 'propfind'

If that happens, does it keep the TCP connection to the SyncEvolution client open? I wonder why libneon doesn't notice the problem.

> And syncevolution blocks, i.e. SIGINT (Ctrl+C) doesn't help it to exit. I
> would have expected to be able to press Ctrl+C to make it return at some
> stage.

Agree, that would be nice. The problem is that libneon doesn't (easily) support integration with an event loop, so once a request is sent, SyncEvolution can only wait for it to complete. I've not found a way to tell libneon that it should abort the currently running request.

There is a mechanisms in SyncEvolution for letting a backend check for abort requests (see the SuspendFlags class) either in polling mode or via an event, but that doesn't help here because SyncEvolution doesn't get the chance to check either of these.
Comment 2 Patrick Ohly 2013-01-16 14:19:47 UTC
One solution proposed on the Neon list is to close the file descriptor used by Neon in a second thread. That should make neon return while blocking on IO via that descriptor.

In SyncEvolution, the main thread would have to be the one which does the closing because that needs to integrate with the main event loop. A second thread would be the one which calls neon.
Comment 3 GitLab Migration User 2018-10-13 12:45:24 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/SyncEvolution/syncevolution/issues/149.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.