summaryrefslogtreecommitdiffstats
path: root/doc/internals/notes-poll-connect.txt
blob: 5cb088515f1471b8b36b62b8932d1e327023c97e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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 ####