You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
5.2 KiB

  1. From c0d56134320e507c82952f3d2a03f76b701945cb Mon Sep 17 00:00:00 2001
  2. From: Willy Tarreau <w@1wt.eu>
  3. Date: Wed, 18 Nov 2015 11:59:55 +0100
  4. Subject: [PATCH 04/10] BUG/MEDIUM: http: switch the request channel to
  5. no-delay once done.
  6. There's an issue when sending POST data that came in a second packet,
  7. the CF_NEVER_WAIT flag is not always set on the request channel, while
  8. the server is waiting for the request. We must always set this flag in
  9. this case since we're not going to shut down after sending, contrary
  10. to the response side.
  11. Note that option http-no-delay works around this issue.
  12. Reproducer :
  13. listen px
  14. mode http
  15. timeout client 10s
  16. timeout server 5s
  17. timeout connect 3s
  18. option http-server-close
  19. #option http-no-delay
  20. bind :8001
  21. server s1 127.0.0.1:8003
  22. $ (printf "POST / HTTP/1.1\r\nTransfer-encoding: chunked\r\n\r\n"; sleep 0.01; printf "10\r\nAZERTYUIOPQSDFGH\r\n0\r\n\r\n") | nc6 0 8001
  23. Before this fix :
  24. 12:03:31.946763 epoll_wait(3, {{EPOLLIN, {u32=5, u64=5}}}, 200, 1000) = 1
  25. 12:03:32.634175 accept4(5, {sa_family=AF_INET, sin_port=htons(53849), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_NONBLOCK) = 6
  26. 12:03:32.634318 setsockopt(6, SOL_TCP, TCP_NODELAY, [1], 4) = 0
  27. 12:03:32.634434 accept4(5, 0x7ffccfbb2cf0, [128], SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)
  28. 12:03:32.634574 recvfrom(6, "POST / HTTP/1.1\r\nTransfer-encodi"..., 8192, 0, NULL, NULL) = 47
  29. 12:03:32.634809 setsockopt(6, SOL_TCP, TCP_QUICKACK, [1], 4) = 0
  30. 12:03:32.634952 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 7
  31. 12:03:32.635031 fcntl(7, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
  32. 12:03:32.635089 setsockopt(7, SOL_TCP, TCP_NODELAY, [1], 4) = 0
  33. 12:03:32.635153 connect(7, {sa_family=AF_INET, sin_port=htons(8003), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
  34. 12:03:32.635315 epoll_wait(3, {}, 200, 0) = 0
  35. 12:03:32.635394 sendto(7, "POST / HTTP/1.1\r\nTransfer-encodi"..., 66, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 66
  36. 12:03:32.635527 recvfrom(6, 0x7f0224e66024, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
  37. 12:03:32.635651 epoll_ctl(3, EPOLL_CTL_ADD, 6, {EPOLLIN|0x2000, {u32=6, u64=6}}) = 0
  38. 12:03:32.635782 epoll_wait(3, {}, 200, 0) = 0
  39. 12:03:32.635842 recvfrom(7, 0x7f0224e66024, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
  40. 12:03:32.635924 epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN|0x2000, {u32=7, u64=7}}) = 0
  41. 12:03:32.636027 epoll_wait(3, {{EPOLLIN, {u32=6, u64=6}}}, 200, 1000) = 1
  42. 12:03:32.644892 recvfrom(6, "10\r\nAZERTYUIOPQSDFGH\r\n0\r\n\r\n", 8192, 0, NULL, NULL) = 27
  43. 12:03:32.645016 epoll_wait(3, {}, 200, 0) = 0
  44. 12:03:32.645105 sendto(7, "10\r\nAZERTYUIOPQSDFGH\r\n0\r\n\r\n", 27, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE, NULL, 0) = 27
  45. After the fix :
  46. 11:59:12.538617 connect(7, {sa_family=AF_INET, sin_port=htons(8003), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
  47. 11:59:12.538787 epoll_wait(3, {}, 200, 0) = 0
  48. 11:59:12.538867 sendto(7, "POST / HTTP/1.1\r\nTransfer-encodi"..., 66, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 66
  49. 11:59:12.539031 recvfrom(6, 0x7f832ce45024, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
  50. 11:59:12.539161 epoll_ctl(3, EPOLL_CTL_ADD, 6, {EPOLLIN|0x2000, {u32=6, u64=6}}) = 0
  51. 11:59:12.539259 epoll_wait(3, {}, 200, 0) = 0
  52. 11:59:12.539337 recvfrom(7, 0x7f832ce45024, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
  53. 11:59:12.539421 epoll_ctl(3, EPOLL_CTL_ADD, 7, {EPOLLIN|0x2000, {u32=7, u64=7}}) = 0
  54. 11:59:12.539499 epoll_wait(3, {{EPOLLIN, {u32=6, u64=6}}}, 200, 1000) = 1
  55. 11:59:12.548519 recvfrom(6, "10\r\nAZERTYUIOPQSDFGH\r\n0\r\n\r\n", 8192, 0, NULL, NULL) = 27
  56. 11:59:12.548844 epoll_wait(3, {}, 200, 0) = 0
  57. 11:59:12.549012 sendto(7, "10\r\nAZERTYUIOPQSDFGH\r\n0\r\n\r\n", 27, MSG_DONTWAIT|MSG_NOSIGNAL, NULL, 0) = 27
  58. 11:59:12.549454 epoll_wait(3, {}, 200, 1000) = 0
  59. This fix must be backported to 1.6, 1.5 and 1.4.
  60. (cherry picked from commit 7f876a1eeb14ffae708327aad8a0b4b029da5e26)
  61. (cherry picked from commit 712a5339f384db62796aa4d4901e091dd7fd24dd)
  62. ---
  63. src/proto_http.c | 9 +++++++--
  64. 1 file changed, 7 insertions(+), 2 deletions(-)
  65. diff --git a/src/proto_http.c b/src/proto_http.c
  66. index e7e1785..b32e778 100644
  67. --- a/src/proto_http.c
  68. +++ b/src/proto_http.c
  69. @@ -5001,6 +5001,13 @@ int http_sync_req_state(struct session *s)
  70. */
  71. chn->cons->flags |= SI_FL_NOHALF;
  72. + /* In any case we've finished parsing the request so we must
  73. + * disable Nagle when sending data because 1) we're not going
  74. + * to shut this side, and 2) the server is waiting for us to
  75. + * send pending data.
  76. + */
  77. + chn->flags |= CF_NEVER_WAIT;
  78. +
  79. if (txn->rsp.msg_state == HTTP_MSG_ERROR)
  80. goto wait_other_side;
  81. @@ -5015,7 +5022,6 @@ int http_sync_req_state(struct session *s)
  82. /* if any side switches to tunnel mode, the other one does too */
  83. channel_auto_read(chn);
  84. txn->req.msg_state = HTTP_MSG_TUNNEL;
  85. - chn->flags |= CF_NEVER_WAIT;
  86. goto wait_other_side;
  87. }
  88. @@ -5048,7 +5054,6 @@ int http_sync_req_state(struct session *s)
  89. if ((txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_TUN) {
  90. channel_auto_read(chn);
  91. txn->req.msg_state = HTTP_MSG_TUNNEL;
  92. - chn->flags |= CF_NEVER_WAIT;
  93. }
  94. }
  95. --
  96. 2.4.10