[ 
https://issues.apache.org/jira/browse/XMLRPC-167?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12706364#action_12706364
 ] 

Alan Burlison commented on XMLRPC-167:
--------------------------------------

I've made XmlRpcStreamTransport.sendRequest synchronized as it is responsible 
for sending the request to the server and receiving the response.  That fixes 
the concurrent read issue, but reveals another problem:

----------
Thread-0: 
InputStreamTracer(sun.net.www.protocol.http.httpurlconnection$httpinputstr...@eac5a)
Thread-0: read() = "<"
Thread-0: read() = "?"
Thread-0: read() = "x"
Thread-0: read() = "m"
Thread-0: read(buff, 0, 28) = 28 "l version="1.0" encoding="UT"
Thread-0: read() = "F"
Thread-0: read() = "-"
Thread-0: read() = "8"
Thread-0: read() = """
Thread-0: read() = "?"
Thread-0: read() = ">"
Thread-0: read(buff, 0, 8192) = 754 
"<methodResponse><params><param><value><struct><member><name>name</name><value>Thread-0</value></member>
 ..."
Thread-0: read(buff, 0, 8192) = -1
Thread-0: close()
Thread-1: java.lang.IllegalStateException: Already connected
    at 
sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:2235)
    at 
sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:296)
    at 
org.apache.xmlrpc.client.XmlRpcSunHttpTransport.setRequestHeader(XmlRpcSunHttpTransport.java:73)
    at 
org.apache.xmlrpc.client.XmlRpcHttpTransport.setContentLength(XmlRpcHttpTransport.java:118)
    at 
org.apache.xmlrpc.client.XmlRpcHttpTransport.newReqWriter(XmlRpcHttpTransport.java:156)
    at 
org.apache.xmlrpc.client.XmlRpcStreamTransport.sendRequest(XmlRpcStreamTransport.java:150)
    at 
org.apache.xmlrpc.client.XmlRpcHttpTransport.sendRequest(XmlRpcHttpTransport.java:143)
    at 
org.apache.xmlrpc.client.XmlRpcSunHttpTransport.sendRequest(XmlRpcSunHttpTransport.java:69)
    at 
org.apache.xmlrpc.client.XmlRpcClientWorker.execute(XmlRpcClientWorker.java:56)
    at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:167)
    at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:137)
    at org.apache.xmlrpc.client.XmlRpcClient.execute(XmlRpcClient.java:126)
    at 
org.opensolaris.auth.client.AuthClient$XmlRpcInvocationHandler.invoke(AuthClient.java:258)
    at $Proxy7.encryptCookie(Unknown Source)
    at authclient.DL.run(Deadlock.java:84)
    at java.lang.Thread.run(Thread.java:619)
Thread-0: 
InputStreamTracer(sun.net.www.protocol.http.httpurlconnection$httpinputstr...@1e13e07)
Thread-0: read() = "<"
Thread-0: read() = "?"
Thread-0: read() = "x"
Thread-0: read() = "m"
Thread-0: read(buff, 0, 28) = 28 "l version="1.0" encoding="UT"
Thread-0: read() = "F"
Thread-0: read() = "-"
Thread-0: read() = "8"
Thread-0: read() = """
Thread-0: read() = "?"
Thread-0: read() = ">"
Thread-0: read(buff, 0, 8192) = 949 
"<methodResponse><params><param><value><struct><member><name>userId</name><value><i4>1</i4></value></member>
 ..."
Thread-0: read(buff, 0, 8192) = -1
Thread-0: close()
----------

Note that unlike the previous case, the reads from the socket are not 
intermixed, and Thread-0 sees the correct response.  Note however the following 
line and the subsequent stack trace:

Thread-1: java.lang.IllegalStateException: Already connected

Here's the issue: The underlying URLConnection has two states - opened and 
connected - see 
http://java.sun.com/javase/6/docs/api/java/net/URLConnection.html.  You can 
only set headers when the UrlConnection is in the opened state, once it becomes 
connected you can't modify headers.  When Thread-0 exits the synchronized 
sendRequest method, Thread-1 acquires the lock, but the shared UrlConnection is 
already in the connected state, so the attempt by Thread-1 to set headers fails.

Which takes us back to my original comment in the bug - XmlRpcClient just 
*isn't* thread-safe, despite what the docs say.  You may get away with using it 
in multi-threaded apps using a transport other than the SunHttpTransport , you 
may get away with running it on a uniprocessor machine, you may get away with 
only running it under light load, but using the Sun transport on a MP machine 
under heavy load it is just plain broken.

I'll carry on investigating and see if I can figure out a fix, but I suspect it 
is going to require either a rewrite or some aggressively coarse-grained 
locking.


> XmlRpcClient is supposed to be thread-safe but it isn't
> -------------------------------------------------------
>
>                 Key: XMLRPC-167
>                 URL: https://issues.apache.org/jira/browse/XMLRPC-167
>             Project: XML-RPC
>          Issue Type: Bug
>          Components: Source
>    Affects Versions: 3.1.2
>         Environment: Solaris
>            Reporter: Alan Burlison
>
> http://ws.apache.org/xmlrpc/apidocs/org/apache/xmlrpc/client/XmlRpcClient.html
>  says:
> ----------
> A configured XmlRpcClient object is thread safe: In other words, the 
> suggested use is, that you configure the client using 
> setTransportFactory(XmlRpcTransportFactory) and similar methods, store it in 
> a field and never modify it again. Without modifications, the client may be 
> used for an arbitrary number of concurrent requests.
> ----------
> I have a simple test case that creates two threads that share a single 
> XmlRpcClient instance, and if I run the test I see the following errors:
> ----------
> Fatal Error] :1:1: Content is not allowed in prolog.
> operation failed, Failed to parse server's response: Content is not allowed 
> in prolog.
> [Fatal Error] :1:10: Element type "xlvrsion" must be followed by either 
> attribute specifications, ">" or "/>".
> operation failed, Failed to parse server's response: Element type "xlvrsion" 
> must be followed by either attribute specifications, ">" or "/>".
> ----------
> ----------
> [Fatal Error] :1:1: Content is not allowed in prolog.
> [Fatal Error] :1:5: Element type "xlv" must be followed by either attribute 
> specifications, ">" or "/>".
> operation failed, Failed to parse server's response: Element type "xlv" must 
> be followed by either attribute specifications, ">" or "/>".
> operation failed, Failed to parse server's response: Content is not allowed 
> in prolog.
> ----------
> If I wrap the call to XmlRpcClient.execute with a synchronized block that 
> locks on the XmlRpcClient object, the code works fine.
> It looks like the execute code is not locking around the read/write to/from 
> the server, so the threads are competing to read the response from the 
> server, and are tripping over each other.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to