Hi Steve,

Could you give a try to the tcp-check and tell us if your have the same issue.
In your backend, turn your httpchk related directives into:
  option tcp-check
  tcp-check send GET\ /cp/testcheck.html\ HTTP/1.0\r\n
  tcp-check send \r\n
  tcp-check expect string good

Baptiste


On Fri, Jan 10, 2014 at 11:16 PM, Steve Ruiz <ste...@mirth.com> wrote:
> I'm experimenting with haproxy on a centos6 VM here.  I found that when I
> specified a health check page (option httpchk GET /url), and that page
> didn't exist, we have a large 404 page returned, and that causes haproxy to
> quickly segfault (seems like on the second try GET'ing and parsing the
> page).  I couldn't figure out from the website where to submit a bug, so I
> figure I'll try here first.
>
> Steps to reproduce:
> - setup http backend, with option httpchk and httpcheck expect string x.
> Make option httpchk point to a non-existent page
> - On backend server, set it up to serve large 404 response (in my case, the
> 404 page is 186kB, as it has an inline graphic and inline css)
> - Start haproxy, and wait for it to segfault
>
> I wasn't sure exactly what was causing this at first, so I did some work to
> narrow it down with GDB.  The variable values from gdb led me to the cause
> on my side, and hopefully can help you fix the issue.  I could not make this
> work with simply a large page for the http response - in that case, it seems
> to work as advertised, only inspecting the response up to tune.chksize
> (default 16384 as i've left it).  But if I do this with a 404, it seems to
> kill it.  Let me know what additional information you need if any.  Thanks
> and kudos for the great bit of software!
>
>
> #haproxy config:
> #---------------------------------------------------------------------
> # Example configuration for a possible web application.  See the
> # full configuration options online.
> #
> #   http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
> #
> #---------------------------------------------------------------------
>
> # Help in developing config here:
> # https://www.twilio.com/engineering/2013/10/16/haproxy
>
>
> #---------------------------------------------------------------------
> # Global settings
> #---------------------------------------------------------------------
> global
>     # to have these messages end up in /var/log/haproxy.log you will
>     # need to:
>     #
>     # 1) configure syslog to accept network log events.  This is done
>     #    by adding the '-r' option to the SYSLOGD_OPTIONS in
>     #    /etc/sysconfig/syslog
>     #
>     # 2) configure local2 events to go to the /var/log/haproxy.log
>     #   file. A line like the following can be added to
>     #   /etc/sysconfig/syslog
>     #
>     #    local2.*                       /var/log/haproxy.log
>     #
>     log         127.0.0.1 local2 info
>
>     chroot      /var/lib/haproxy
>     pidfile     /var/run/haproxy.pid
>     maxconn     4000
>     user        haproxy
>     group       haproxy
>     daemon
>
>     #enable stats
>     stats socket /tmp/haproxy.sock
>
> listen ha_stats :8088
>     balance source
>     mode http
>     timeout client 30000ms
>     stats enable
>     stats auth haproxystats:foobar
>     stats uri /haproxy?stats
>
> #---------------------------------------------------------------------
> # common defaults that all the 'listen' and 'backend' sections will
> # use if not designated in their block
> #---------------------------------------------------------------------
> defaults
>     mode                    http
>     log                     global
>     option                  httplog
>     option                  dontlognull
>     #keep persisten client connection open
>     option                  http-server-close
>     option forwardfor       except 127.0.0.0/8
>     option                  redispatch
>     # Limit number of retries - total time trying to connect = connect
> timeout * (#retries + 1)
>     retries                 2
>     timeout http-request    10s
>     timeout queue           1m
>     #timeout opening a tcp connection to server - should be shorter than
> timeout client and server
>     timeout connect         3100
>     timeout client          30s
>     timeout server          30s
>     timeout http-keep-alive 10s
>     timeout check           10s
>     maxconn                 3000
>
> #---------------------------------------------------------------------
> # main frontend which proxys to the backends
> #---------------------------------------------------------------------
> frontend https_frontend
> bind :80
> redirect scheme https if !{ ssl_fc }
>
> #config help:
> https://github.com/observing/balancerbattle/blob/master/haproxy.cfg
> bind *:443 ssl crt /etc/certs/mycert.pem ciphers
> RC4-SHA:AES128-SHA:AES:!ADH:!aNULL:!DH:!EDH:!eNULL
> mode http
> default_backend webapp
>
> #---------------------------------------------------------------------
> # Main backend for web application servers
> #---------------------------------------------------------------------
> backend webapp
>     balance     roundrobin
>     #Insert cookie SERVERID to pin it to one leg
>     cookie SERVERID insert nocache indirect
>     #http check should pull url below
>     option httpchk GET /cp/testcheck.html HTTP/1.0
>     #option httpchk GET /cp/testcheck.php HTTP/1.0
>     #http check should find string below in response to be considered up
>     http-check expect string good
>     #Define servers - inter=interval of 5s, rise 2=become avail after 2
> successful checks, fall 3=take out after 3 fails
>     server app1 app1.myco.com:80 weight 5 cookie app1 check inter 5000 rise
> 2 fall 3
>     server app2 app2.myco.com:80 weight 5 cookie app1 check inter 5000 rise
> 2 fall 3
>     #Example sorry server
>     #server backup host.name:80 backup
>
> #---------------------------------------------------------------------
> # Balancing for postfix / smtp
> #---------------------------------------------------------------------
> listen smtp 10.40.60.25:25
>     option tcpka
>     mode tcp
>     option tcplog
>     balance roundrobin
>     server app1 app1.myco.com:25 check inter 20000
>     server app2 app2.myco.com:25 check inter 20000
>
>
> GDB STack trace:
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 0x7ffff7fea7c0 (LWP 6083)]
> 0x00007ffff6e22c64 in memcpy () from /lib64/libc.so.6
> Missing separate debuginfos, use: debuginfo-install
> glibc-2.12-1.132.el6.x86_64 keyutils-libs-1.4-4.el6.x86_64
> krb5-libs-1.10.3-10.el6_4.6.x86_64 libcom_err-1.41.12-18.el6.x86_64
> libselinux-2.0.94-5.3.el6_4.1.x86_64 nss-softokn-freebl-3.14.3-9.el6.x86_64
> openssl-1.0.1e-16.el6_5.1.x86_64 pcre-7.8-6.el6.x86_64
> zlib-1.2.3-29.el6.x86_64
> (gdb) bt
> #0  0x00007ffff6e22c64 in memcpy () from /lib64/libc.so.6
> #1  0x0000000000423b42 in bo_putblk (b=0x6eff90, blk=0x6d82d0 "GET
> /cp/testcheck.php HTTP/1.0\r\n", len=32)
>     at include/common/buffer.h:388
> #2  0x0000000000425963 in process_chk (t=0x70fd80) at src/checks.c:1536
> #3  0x000000000040e7e0 in process_runnable_tasks (next=0x7fffffffe45c) at
> src/task.c:240
> #4  0x00000000004051d0 in run_poll_loop () at src/haproxy.c:1278
> #5  0x00000000004075f1 in main (argc=<value optimized out>, argv=<value
> optimized out>) at src/haproxy.c:1609
> (gdb)
>
> Full GDB output:
> [root@proxy1 ~]# gdb --args /usr/sbin/haproxy  -Ds -f
> /etc/haproxy/haproxy.cfg
> GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
> Copyright (C) 2010 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "x86_64-redhat-linux-gnu".
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>...
> Reading symbols from /usr/sbin/haproxy...Reading symbols from
> /usr/lib/debug/usr/sbin/haproxy.debug...done.
> done.
> (gdb) set follow-fork-mode child
> (gdb) break src/checks.c:1536
> Breakpoint 1 at 0x425949: file src/checks.c, line 1536.
> (gdb) run
> Starting program: /usr/sbin/haproxy -Ds -f /etc/haproxy/haproxy.cfg
> [Thread debugging using libthread_db enabled]
> [WARNING] 009/124757 (7470) : config : 'option forwardfor' ignored for proxy
> 'smtp' as it requires HTTP mode.
> [WARNING] 009/124757 (7470) : config : 'option http-server-close' ignored
> for proxy 'smtp' as it requires HTTP mode.
> [New process 7473]
> [Thread debugging using libthread_db enabled]
> [Switching to Thread 0x7ffff7fea7c0 (LWP 7473)]
>
> Breakpoint 1, process_chk (t=0x70fd00) at src/checks.c:1536
> 1536 bo_putblk(check->bo, s->proxy->check_req, s->proxy->check_len);
> Missing separate debuginfos, use: debuginfo-install
> glibc-2.12-1.132.el6.x86_64 keyutils-libs-1.4-4.el6.x86_64
> krb5-libs-1.10.3-10.el6_4.6.x86_64 libcom_err-1.41.12-18.el6.x86_64
> libselinux-2.0.94-5.3.el6_4.1.x86_64 nss-softokn-freebl-3.14.3-9.el6.x86_64
> openssl-1.0.1e-16.el6_5.1.x86_64 pcre-7.8-6.el6.x86_64
> zlib-1.2.3-29.el6.x86_64
> (gdb) continue
> Continuing.
>
> Breakpoint 1, process_chk (t=0x70fd80) at src/checks.c:1536
> 1536 bo_putblk(check->bo, s->proxy->check_req, s->proxy->check_len);
> (gdb) continue
> Continuing.
>
> Breakpoint 1, process_chk (t=0x70fd00) at src/checks.c:1536
> 1536 bo_putblk(check->bo, s->proxy->check_req, s->proxy->check_len);
> (gdb) continue
> Continuing.
>
> Breakpoint 1, process_chk (t=0x70fd80) at src/checks.c:1536
> 1536 bo_putblk(check->bo, s->proxy->check_req, s->proxy->check_len);
> (gdb) step
> bo_putblk (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:375
> 375 {
> (gdb) step
> 379 if (len > b->size - cur_len)
> (gdb) step
> 376 int cur_len = buffer_len(b);
> (gdb) step
> buffer_len (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:151
> 151 return buf->i + buf->o;
> (gdb) step
> bo_putblk (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:375
> 375 {
> (gdb) step
> 376 int cur_len = buffer_len(b);
> (gdb) step
> buffer_len (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:151
> 151 return buf->i + buf->o;
> (gdb) step
> 379 if (len > b->size - cur_len)
> (gdb) step
> bo_putblk (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:380
> 380 len = (b->size - cur_len);
> (gdb) step
> 381 if (!len)
> (gdb) step
> 384 half = buffer_contig_space(b);
> (gdb) step
> buffer_contig_space (b=<value optimized out>, blk=0x6d82d0 "GET
> /cp/testcheck.php HTTP/1.0\r\n", len=32)
>     at include/common/buffer.h:222
> 222 if (buf->data + buf->o <= buf->p)
> (gdb) step
> 223 right = buf->data + buf->size;
> (gdb) step
> 222 if (buf->data + buf->o <= buf->p)
> (gdb) step
> 223 right = buf->data + buf->size;
> (gdb) step
> 222 if (buf->data + buf->o <= buf->p)
> (gdb) step
> 227 left = buffer_wrap_add(buf, buf->p + buf->i);
> (gdb) step
> buffer_wrap_add (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php
> HTTP/1.0\r\n", len=32) at include/common/buffer.h:191
> 191 if (ptr - buf->size >= buf->data)
> (gdb) step
> bo_putblk (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:388
> 388 memcpy(b->p, blk, half);
> (gdb) print b->p
> $1 = 0x6effa4 "play:table-column;float:none}table td[class*=\"col-\"],table
> th[class*=\"col-\"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr"...
> (gdb) print blk
> $2 = 0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n"
> (gdb) print half
> $3 = <value optimized out>
> (gdb)
> $4 = <value optimized out>
> (gdb) step
> 384 half = buffer_contig_space(b);
> (gdb) step
> buffer_contig_space (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php
> HTTP/1.0\r\n", len=32) at include/common/buffer.h:227
> 227 left = buffer_wrap_add(buf, buf->p + buf->i);
> (gdb) step
> buffer_wrap_add (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php
> HTTP/1.0\r\n", len=32) at include/common/buffer.h:191
> 191 if (ptr - buf->size >= buf->data)
> (gdb) step
> buffer_contig_space (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php
> HTTP/1.0\r\n", len=32) at include/common/buffer.h:228
> 228 return right - left;
> (gdb) step
> bo_putblk (b=0x6eff90, blk=0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n",
> len=32) at include/common/buffer.h:388
> 388 memcpy(b->p, blk, half);
> (gdb) print b->p
> $5 = 0x6effa4 "play:table-column;float:none}table td[class*=\"col-\"],table
> th[class*=\"col-\"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr"...
> (gdb) print blk
> $6 = 0x6d82d0 "GET /cp/testcheck.php HTTP/1.0\r\n"
> (gdb) print half
> $7 = -2119952626
> (gdb)
> $8 = -2,119,952,626
> (gdb) step
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007ffff6e22c64 in memcpy () from /lib64/libc.so.6
>
>
>
>
> Steve Ruiz
> Manager - Hosting Operations
> Mirth
> ste...@mirth.com
>
> CONFIDENTIALITY NOTICE: The information contained in this electronic
> transmission may be confidential. If you are not an intended recipient, be
> aware that any disclosure, copying, distribution or use of the information
> contained in this transmission is prohibited and may be unlawful. If you
> have received this transmission in error, please notify us by email reply
> and then erase it from your computer system.

Reply via email to