On Wed, Mar 6, 2019 at 9:21 AM Tom Lane <t...@sss.pgh.pa.us> wrote: > The bug #15598 report is more troublesome, as we don't have a strong > reason to believe it's not common on Windows. However, I wonder whether > we can really do anything at all about that one. If I understand what > Andrew was hypothesizing in that thread, it was that Windows might be > dropping undelivered data on the floor once the server closes its end > of the connection. That would be totally broken behavior, but I never > expect anything else from Microsoft :-(. If that is an accurate theory > then rewriting libpq won't fix it.
Here is a stupid Python 2.7 program to try to test that. Run one copy of it like this: $ python ./test.py --server The server will wait for a client, send a message immediately, and then close the socket after a second. The client will connect and send something once before and twice after the server closes the socket, and finally see if it can read the message from the server. Here's the output I get from the client on some different systems (the server was running on the same system): $ uname -a Linux debian 4.18.0-3-amd64 #1 SMP Debian 4.18.20-2 (2018-11-23) x86_64 GNU/Linux $ python ./test.py --client Sending A... 2 Sending B... [Errno 104] Connection reset by peer Sending C... [Errno 32] Broken pipe This is the server saying goodbye $ uname -a Darwin macaque.local 18.2.0 Darwin Kernel Version 18.2.0: Thu Dec 20 20:46:53 PST 2018; root:xnu-4903.241.1~1/RELEASE_X86_64 x86_64 $ python2.7 ./test.py --client Sending A... 2 Sending B... [Errno 32] Broken pipe Sending C... [Errno 32] Broken pipe This is the server saying goodbye $ uname -a FreeBSD dogmatix 13.0-CURRENT FreeBSD 13.0-CURRENT c0873ea614a(master) GENERIC amd64 $ python2.7 ./test.py --client Sending A... 2 Sending B... 2 Sending C... 2 This is the server saying goodbye So... can anyone tell us what happens on Windows? (A secondary question might be what happens if the server and client are on different machines since I guess it could be different?) -- Thomas Munro https://enterprisedb.com
import socket import sys import time address = ("localhost", 8888) def server(): ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ss.bind(address) ss.listen(5) (s, other_address) = ss.accept() # Send a message, but then close the socket shortly after. # Will the client manage to read the goodbye message, if it tries to write # first? s.send("This is the server saying goodbye\n") time.sleep(1) s.close() def client(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(address) # Try to send a message immediately. At this point we expect the server # end to be waiting for a second before closing, so it should be OK. try: print "Sending A..." sent = s.send("A\n") print sent except Exception, e: # (Should not be reached) print e # Wait until after the server has closed its socket, and try to send # another message. time.sleep(2) try: print "Sending B..." sent = s.send("B\n") print sent except Exception, e: # We expect an error either here or at the next write (?) print e # Send one more message, just to see if perhaps an error will be reported # here rather than earlier... try: print "Sending C..." sent = s.send("C\n") print sent except Exception, e: # What about now? print e # Can we read the goodbye message? print s.recv(1024) if __name__ == "__main__": if sys.argv[1] == "--server": server() elif sys.argv[1] == "--client": client()