[
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.