blob: 5cb088515f1471b8b36b62b8932d1e327023c97e [file] [log] [blame]
Willy Tarreau831d6132022-11-17 16:14:23 +010012022-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 ####