Re: invalid message format and I/O error while comunicating with backend - Mailing list pgsql-jdbc
From | Kris Jurka |
---|---|
Subject | Re: invalid message format and I/O error while comunicating with backend |
Date | |
Msg-id | 481901F4.1070302@ejurka.com Whole thread Raw |
In response to | invalid message format and I/O error while comunicating with backend (Sergi Vera <svera@emovilia.com>) |
Responses |
Re: invalid message format and I/O error while comunicating
with backend
|
List | pgsql-jdbc |
This appears to be a thread safety related problem. I believe your code has one thread setting the parameter values and another thread executing the prepared statement at the same time. The executor does two passes through the parameter list, once to calculate a total message length and another time to send the values. If the contents change between the length calculation and the message sending we'll have the wrong length and the whole client-server communication gets messed up. The attached test case demonstrates this failure mode. I'm unsure how hard we should try to fix this, there are a couple of approaches: 1) Do nothing. It's really a client problem and they shouldn't be setting and executing at the same time. 2) Just copy the parameters at execution time so we get a consistent view of them. This may not be exactly what the user wants though if the order things actually execute is: execute, set, copy instead of execute, copy, set. 3) Go through all the PreparedStatement functions making most of them synchronized so that you cannot set while an execute is running. Kris Jurka Sergi Vera wrote: > Hi! > > I've been a little busy thoose days and was unable to work on this, but > I've made the tcpdump session that you requested and > here are the results > > > Kris Jurka escribió: >> Sergi Vera wrote: >>> Thanks Kris for the help >>> >>> Adding loglevel=2 dind't add any more info on logs, and it will be >>> not easy to make a self contained program, but I have attached the >>> result of >> >> The loglevel=2 logging will go to the driver's System.out not into the >> server error log. >> >>> tcpdump -vvv -i lo -w pgsqlerror2.dat >>> >> >> This only captures the start of each packet so it doesn't have the >> whole thing. Could you recapture with: >> >> tcpdump -n -w pgsqlerror3.dat -s 1514 -i any tcp port 5432 >> >> This ups the capture size (-s 1514) and also filters out the unrelated >> UDP traffic you've got going on. >> >>> Browsing through the first failing pgsql data chunk, one can see that: >>> >>> http://img139.imageshack.us/my.php?image=pantallazolm8.png >>> >>> The last data has column lenght -1 which seems strange even if I >>> don'k know anything of this particular protocol >>> >> >> -1 length indicates a NULL value, so that's expected. >> > > import java.sql.*; public class ThreadPS { public static void main(String args[]) throws Exception { Class.forName("org.postgresql.Driver"); Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/jurka","jurka",""); Statement stmt = conn.createStatement(); stmt.execute("CREATE TEMP TABLE threadps (a int, b text, c text)"); stmt.close(); PreparedStatement ps = conn.prepareStatement("INSERT INTO threadps VALUES (?,?,?)"); ps.setInt(1,0); ps.setString(2, "0"); ps.setString(3, ""); Executor exec = new Executor(ps); new Thread(exec, "Exec").start(); Setter set = new Setter(ps); new Thread(set, "Set").start(); } static class Executor implements Runnable { private PreparedStatement ps; Executor(PreparedStatement ps) { this.ps = ps; } public void run() { while (true) { try { ps.executeUpdate(); } catch (SQLException sqle) { sqle.printStackTrace(); System.exit(1); } } } } static class Setter implements Runnable { private PreparedStatement ps; Setter(PreparedStatement ps) { this.ps = ps; } public void run() { int count = 0; while (true) { try { if (count++ % 2 == 0) { ps.setInt(1,10); ps.setString(2, "aa"); ps.setString(3, "bb"); } else { ps.setInt(1, 1); ps.setString(2, "a"); ps.setString(3, "b"); } } catch (SQLException sqle) { sqle.printStackTrace(); System.exit(1); } } } } }
pgsql-jdbc by date: