Willy Tarreau | 831d613 | 2022-11-17 16:14:23 +0100 | [diff] [blame] | 1 | 2022-11-17 - Tests involving poll() return states upon a pending connect(). |
| 2 | |
| 3 | - connect() to a closed port returns OUT and HUP: |
| 4 | |
| 5 | $ dev/poll/poll -v -l clo -c pol |
| 6 | #### BEGIN #### |
| 7 | cmd #1 stp #1: clo(l=3): ret=0 |
| 8 | cmd #2 stp #0: con(c=4): ret=-1 (Connection refused) |
| 9 | cmd #2 stp #1: pol(c=4): ret=1 ev=0x14 (OUT HUP) |
| 10 | #### END #### |
| 11 | |
| 12 | => with HUP we *know* the connection failed, since we never asked for a |
| 13 | SHUTW before connecting. It is indeed an error as can be seen with |
| 14 | connect() returning -1 ECONNREFUSED. |
| 15 | |
| 16 | - connect() to a port that does close(accept()) does return IN and RDHUP: |
| 17 | |
| 18 | $ dev/poll/poll -v -s clo -c pol |
| 19 | #### BEGIN #### |
| 20 | cmd #1 stp #0: con(c=4): ret=0 |
| 21 | cmd #1 stp #0: acc(l=3): ret=5 |
| 22 | cmd #1 stp #1: clo(s=5): ret=0 |
| 23 | cmd #2 stp #1: pol(c=4): ret=1 ev=0x2005 (IN OUT RDHUP) |
| 24 | #### END #### |
| 25 | |
| 26 | => here there's no HUP, only RDHUP because the FIN is pending in the |
| 27 | socket buffers, waiting to be read. |
| 28 | |
| 29 | - for a HUP to happen after a connect() to a valid port, one would have to |
| 30 | perform a shutw() on the client, which is normally not the case, indicating |
| 31 | that HUP is reliable here: |
| 32 | |
| 33 | $ dev/poll/poll -v -s clo -c shw,pol |
| 34 | #### BEGIN #### |
| 35 | cmd #1 stp #0: con(c=4): ret=0 |
| 36 | cmd #1 stp #0: acc(l=3): ret=5 |
| 37 | cmd #1 stp #1: clo(s=5): ret=0 |
| 38 | cmd #2 stp #1: shw(c=4): ret=0 |
| 39 | cmd #2 stp #2: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP) |
| 40 | #### END #### |
| 41 | |
| 42 | - one case that may happen is when sending a request and immediately shutw() |
| 43 | (which leaves a TIME_WAIT so not recommended): |
| 44 | |
| 45 | $ dev/poll/poll -v -c snd,shw -s clo -c pol,rcv,pol |
| 46 | #### BEGIN #### |
| 47 | cmd #1 stp #0: con(c=4): ret=0 |
| 48 | cmd #1 stp #1: snd(c=4): ret=3 |
| 49 | cmd #1 stp #2: shw(c=4): ret=0 |
| 50 | cmd #2 stp #0: acc(l=3): ret=5 |
| 51 | cmd #2 stp #1: clo(s=5): ret=0 |
| 52 | cmd #3 stp #1: pol(c=4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP) |
| 53 | cmd #3 stp #2: rcv(c=4): ret=-1 (Connection reset by peer) |
| 54 | cmd #3 stp #3: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP) |
| 55 | #### END #### |
| 56 | |
| 57 | => here it's impossible to know from the client whether the server consumed the |
| 58 | data or not, which is normal since a close on the server causes an RST to be |
| 59 | emitted for the data in flight, hence the ERR here. It's also worth noting |
| 60 | that once POLL_ERR is consumed by recv() it disappears. |
| 61 | |
| 62 | - for the server, sending a shutw() before closing here delivers an ACK in time |
| 63 | that prevents the RST from being sent, thus connect() is not notified (but if |
| 64 | the server has too much to send, it will truncate and emit an RST): |
| 65 | |
| 66 | $ dev/poll/poll -v -c snd,shw -s shw,clo -c pol,rcv,pol |
| 67 | #### BEGIN #### |
| 68 | cmd #1 stp #0: con(c=4): ret=0 |
| 69 | cmd #1 stp #1: snd(c=4): ret=3 |
| 70 | cmd #1 stp #2: shw(c=4): ret=0 |
| 71 | cmd #2 stp #0: acc(l=3): ret=5 |
| 72 | cmd #2 stp #1: shw(s=5): ret=0 |
| 73 | cmd #2 stp #2: clo(s=5): ret=0 |
| 74 | cmd #3 stp #1: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP) |
| 75 | cmd #3 stp #2: rcv(c=4): ret=0 |
| 76 | cmd #3 stp #3: pol(c=4): ret=1 ev=0x2015 (IN OUT HUP RDHUP) |
| 77 | #### END #### |
| 78 | |
| 79 | - if the server sends a response, disables lingering and closes with RST, it is |
| 80 | possible to get HUP and ERR at the same time during the connect() phase, and |
| 81 | recv() can still receive the pending response: |
| 82 | |
| 83 | $ dev/poll/poll -v -s snd,lin,clo -c pol,rcv,pol |
| 84 | #### BEGIN #### |
| 85 | cmd #1 stp #0: con(c=4): ret=0 |
| 86 | cmd #1 stp #0: acc(l=3): ret=5 |
| 87 | cmd #1 stp #1: snd(s=5): ret=3 |
| 88 | cmd #1 stp #2: lin(s=5): ret=0 |
| 89 | cmd #1 stp #3: clo(s=5): ret=0 |
| 90 | cmd #2 stp #1: pol(c=4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP) |
| 91 | cmd #2 stp #2: rcv(c=4): ret=3 |
| 92 | cmd #2 stp #3: pol(c=4): ret=1 ev=0x201d (IN OUT ERR HUP RDHUP) |
| 93 | #### END #### |