mirror of
				https://git.haproxy.org/git/haproxy.git/
				synced 2025-10-31 16:41:01 +01:00 
			
		
		
		
	Let's keep these notes as references for later use. Polling on connect() can sometimes return a few unexpected state combinations that such tests illustrate. They can serve as reminders for special error handling.
		
			
				
	
	
		
			94 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			94 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 2022-11-17 - Tests involving poll() return states upon a pending connect().
 | |
| 
 | |
| - connect() to a closed port returns OUT and HUP:
 | |
| 
 | |
|   $ dev/poll/poll -v -l clo -c pol
 | |
|   #### BEGIN ####
 | |
|   cmd #1 stp #1: clo(l=3): ret=0
 | |
|   cmd #2 stp #0: con(c=4): ret=-1 (Connection refused)
 | |
|   cmd #2 stp #1: pol(c=4): ret=1 ev=0x14 (OUT HUP)
 | |
|   #### END ####
 | |
| 
 | |
| => with HUP we *know* the connection failed, since we never asked for a
 | |
|    SHUTW before connecting. It is indeed an error as can be seen with
 | |
|    connect() returning -1 ECONNREFUSED.
 | |
| 
 | |
| - connect() to a port that does close(accept()) does return IN and RDHUP:
 | |
| 
 | |
|   $ dev/poll/poll -v -s clo -c pol
 | |
|   #### BEGIN ####
 | |
|   cmd #1 stp #0: con(c=4): ret=0
 | |
|   cmd #1 stp #0: acc(l=3): ret=5
 | |
|   cmd #1 stp #1: clo(s=5): ret=0
 | |
|   cmd #2 stp #1: pol(c=4): ret=1 ev=0x2005 (IN OUT RDHUP)
 | |
|   #### END ####
 | |
| 
 | |
| => here there's no HUP, only RDHUP because the FIN is pending in the
 | |
|    socket buffers, waiting to be read.
 | |
| 
 | |
| - for a HUP to happen after a connect() to a valid port, one would have to
 | |
|   perform a shutw() on the client, which is normally not the case, indicating
 | |
|   that HUP is reliable here:
 | |
| 
 | |
|   $ dev/poll/poll -v -s clo -c shw,pol
 | |
|   #### BEGIN ####
 | |
|   cmd #1 stp #0: con(c=4): ret=0
 | |
|   cmd #1 stp #0: acc(l=3): ret=5
 | |
|   cmd #1 stp #1: clo(s=5): ret=0
 | |
|   cmd #2 stp #1: shw(c=4): ret=0
 | |
|   cmd #2 stp #2: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP)
 | |
|   #### END ####
 | |
| 
 | |
| - one case that may happen is when sending a request and immediately shutw()
 | |
|   (which leaves a TIME_WAIT so not recommended):
 | |
| 
 | |
|   $ dev/poll/poll -v -c snd,shw -s clo -c pol,rcv,pol
 | |
|   #### BEGIN ####
 | |
|   cmd #1 stp #0: con(c=4): ret=0
 | |
|   cmd #1 stp #1: snd(c=4): ret=3
 | |
|   cmd #1 stp #2: shw(c=4): ret=0
 | |
|   cmd #2 stp #0: acc(l=3): ret=5
 | |
|   cmd #2 stp #1: clo(s=5): ret=0
 | |
|   cmd #3 stp #1: pol(c=4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP)
 | |
|   cmd #3 stp #2: rcv(c=4): ret=-1 (Connection reset by peer)
 | |
|   cmd #3 stp #3: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP)
 | |
|   #### END ####
 | |
| 
 | |
| => here it's impossible to know from the client whether the server consumed the
 | |
|    data or not, which is normal since a close on the server causes an RST to be
 | |
|    emitted for the data in flight, hence the ERR here. It's also worth noting
 | |
|    that once POLL_ERR is consumed by recv() it disappears.
 | |
| 
 | |
| - for the server, sending a shutw() before closing here delivers an ACK in time
 | |
|   that prevents the RST from being sent, thus connect() is not notified (but if
 | |
|   the server has too much to send, it will truncate and emit an RST):
 | |
| 
 | |
|   $ dev/poll/poll -v -c snd,shw -s shw,clo -c pol,rcv,pol
 | |
|   #### BEGIN ####
 | |
|   cmd #1 stp #0: con(c=4): ret=0
 | |
|   cmd #1 stp #1: snd(c=4): ret=3
 | |
|   cmd #1 stp #2: shw(c=4): ret=0
 | |
|   cmd #2 stp #0: acc(l=3): ret=5
 | |
|   cmd #2 stp #1: shw(s=5): ret=0
 | |
|   cmd #2 stp #2: clo(s=5): ret=0
 | |
|   cmd #3 stp #1: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP)
 | |
|   cmd #3 stp #2: rcv(c=4): ret=0
 | |
|   cmd #3 stp #3: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP)
 | |
|   #### END ####
 | |
| 
 | |
| - if the server sends a response, disables lingering and closes with RST, it is
 | |
|   possible to get HUP and ERR at the same time during the connect() phase, and
 | |
|   recv() can still receive the pending response:
 | |
| 
 | |
|   $ dev/poll/poll -v -s snd,lin,clo -c pol,rcv,pol
 | |
|   #### BEGIN ####
 | |
|   cmd #1 stp #0: con(c=4): ret=0
 | |
|   cmd #1 stp #0: acc(l=3): ret=5
 | |
|   cmd #1 stp #1: snd(s=5): ret=3
 | |
|   cmd #1 stp #2: lin(s=5): ret=0
 | |
|   cmd #1 stp #3: clo(s=5): ret=0
 | |
|   cmd #2 stp #1: pol(c=4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP)
 | |
|   cmd #2 stp #2: rcv(c=4): ret=3
 | |
|   cmd #2 stp #3: pol(c=4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP)
 | |
|   #### END ####
 |