>=3.2-dev8: Hanging stats socket with cpu-policy group-by-cluster · Issue #2951 · haproxy/haproxy · GitHub
Skip to content

>=3.2-dev8: Hanging stats socket with cpu-policy group-by-cluster #2951

Closed

Description

@idl0r

Detailed Description of the Problem

Regarding https://github.com/orgs/haproxy/discussions/2901#discussioncomment-12934325

Our config and systems were unmodified and are running very stable for quite some time with 3.1.6 (except one rare but already fixed issue in 3.1.7) and 3.2-dev (currently -dev11, started with dev0) and never had this problem.
When adding cpu-policy group-by-cluster to the global section, HAProxy becomes unresponsive / blocking after some time but it seems only for the stats socket. It seems to still serve traffic. Reload doesn't help, only restart.

It is unclear yet what's triggering this issue. It's not immediately and it takes some minutes (usually <10m). A reload isn't required to trigger it it seems.

Expected Behavior

Working stats socket

Steps to Reproduce the Behavior

  1. 3.2-dev11
  2. cpu-policy group-by-cluster in the global section
  3. some magic
  4. echo help | socat /path/to/socket stdio
  5. Get no response and/or blocking connections to the socket (not socat tho) and high CPU usage

Do you have any idea what may have caused this?

Somehow related to cpu-policy group-by-cluster

Do you have an idea how to solve the issue?

No response

What is your configuration?

N/A

Output of haproxy -vv

HAProxy version 3.2-dev11-acd372d 2025/04/18 - https://haproxy.org/
Status: development branch - not safe for use in production.
Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open
Running on: Linux 6.1.0-33-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.133-1 (2025-04-10) x86_64
Build options : 
  TARGET  = linux-glibc
  CC      = cc
  CFLAGS  = -O2 -g -march=x86-64-v3 -mtune=znver1 -fwrapv
  OPTIONS = USE_LIBCRYPT=1 USE_OPENSSL_AWSLC=1 USE_LUA=1 USE_ZLIB= USE_SLZ=1 USE_NS= USE_PROMEX=1 USE_PCRE= USE_PCRE_JIT= USE_PCRE2=1 USE_PCRE2_JIT=
  DEBUG   = -DDEBUG_GLITCHES=1

Feature list : -51DEGREES +ACCEPT4 +BACKTRACE -CLOSEFROM +CPU_AFFINITY +CRYPT_H -DEVICEATLAS +DL -ENGINE +EPOLL -EVPORTS +GETADDRINFO -KQUEUE -LIBATOMIC +LIBCRYPT +LINUX_CAP +LINUX_SPLICE +LINUX_TPROXY +LUA +MATH -MEMORY_PROFILING +NETFILTER -NS -OBSOLETE_LINKER +OPENSSL +OPENSSL_AWSLC -OPENSSL_WOLFSSL -OT -PCRE +PCRE2 -PCRE2_JIT -PCRE_JIT +POLL +PRCTL -PROCCTL +PROMEX -PTHREAD_EMULATION -QUIC -QUIC_OPENSSL_COMPAT +RT +SLZ +SSL -STATIC_PCRE -STATIC_PCRE2 +TFO +THREAD +THREAD_DUMP +TPROXY -WURFL -ZLIB

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_TGROUPS=16, MAX_THREADS=256, default=4).
Built with SSL library version : OpenSSL 1.1.1 (compatible; AWS-LC 1.49.1)
Running on SSL library version : AWS-LC 1.49.1
SSL library supports TLS extensions : yes
SSL library supports SNI : yes
SSL library FIPS mode : no
SSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.6
Built with the Prometheus exporter as a service
Built with libslz for stateless compression.
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE2 version : 10.42 2022-12-11
PCRE2 library supports JIT : no (USE_PCRE2_JIT not set)
Encrypted password support via crypt(3): yes
Built with gcc compiler version 12.2.0

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
         h2 : mode=HTTP  side=FE|BE  mux=H2    flags=HTX|HOL_RISK|NO_UPG
  <default> : mode=HTTP  side=FE|BE  mux=H1    flags=HTX
         h1 : mode=HTTP  side=FE|BE  mux=H1    flags=HTX|NO_UPG
       fcgi : mode=HTTP  side=BE     mux=FCGI  flags=HTX|HOL_RISK|NO_UPG
  <default> : mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG
       spop : mode=SPOP  side=BE     mux=SPOP  flags=HOL_RISK|NO_UPG
  <default> : mode=TCP   side=FE|BE  mux=PASS  flags=
       none : mode=TCP   side=FE|BE  mux=PASS  flags=NO_UPG

Available services : prometheus-exporter
Available filters :
	[BWLIM] bwlim-in
	[BWLIM] bwlim-out
	[CACHE] cache
	[COMP] compression
	[FCGI] fcgi-app
	[SPOE] spoe
	[TRACE] trace

Last Outputs and Backtraces


Additional Information

No response

Activity

  1. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    @wtarreau I'm trying to reproduce it with -dev8 right now. I'll also try to get you some gdb output / coredump or something.
    If dev8 is also affected, I can also try to bisect it further but it might be ending up in the commit that adds cpu-policy group-by-cluster. So not sure if that will be that helpful then.

  2. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    Does your monitoring script send any "show sess" or long dumps that may use more than one buffer ? Or does it add/remove servers maybe ?

    It's doing a show stat and a show info for parsing some data. We have like 15 of those checks and they're issued around every 5m. The script then parses the output and is looking for a specific proxy

  3. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    @wtarreau I'm trying to reproduce it with -dev8 right now. I'll also try to get you some gdb output / coredump or something. If dev8 is also affected, I can also try to bisect it further but it might be ending up in the commit that adds cpu-policy group-by-cluster. So not sure if that will be that helpful then.

    Can be triggered and reproduced with -dev8!. Hope that helps already somewhat.

    Image

  4. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    OK thanks for the info. So if you say it usually takes less than 10mn, we could imagine that the python script passes at most once or twice before it happens, so maybe it manages to trigger the issue by dumping such stats and info.

    Before you spend a lot of time bisecting, I'd suggest to instead try to manually configure the groups like the cpu-policy does it:

        thread-groups 8
        cpu-map 1/1-16 0-7   64-71
        cpu-map 2/1-16 8-15  72-79
        cpu-map 3/1-16 16-23 80-87
        cpu-map 4/1-16 24-31 88-95
        cpu-map 5/1-16 32-39 96-103
        cpu-map 6/1-16 40-47 104-111
        cpu-map 7/1-16 48-55 112-119
        cpu-map 8/1-16 56-63 120-127
    

    Logically it should reproduce the issue. My fear is that we could have a deeper bug somewhere in file descriptor management or any such thing when it comes to thread groups, and that could be more easily triggered by your setup than others.

  5. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    OK thanks for the info. So if you say it usually takes less than 10mn, we could imagine that the python script passes at most once or twice before it happens, so maybe it manages to trigger the issue by dumping such stats and info.

    Before you spend a lot of time bisecting, I'd suggest to instead try to manually configure the groups like the cpu-policy does it:

        thread-groups 8
        cpu-map 1/1-16 0-7   64-71
        cpu-map 2/1-16 8-15  72-79
        cpu-map 3/1-16 16-23 80-87
        cpu-map 4/1-16 24-31 88-95
        cpu-map 5/1-16 32-39 96-103
        cpu-map 6/1-16 40-47 104-111
        cpu-map 7/1-16 48-55 112-119
        cpu-map 8/1-16 56-63 120-127
    

    Logically it should reproduce the issue. My fear is that we could have a deeper bug somewhere in file descriptor management or any such thing when it comes to thread groups, and that could be more easily triggered by your setup than others.

    Can do!
    I wanted to do that on that semi productive node so the mappings above will not work. This one seems totally different:

    # haproxy -f /etc/haproxy/haproxy.cfg -dc -c
    [keep] cpu=  0 pk=00 no=00 cl=000(000) l3=000 l2=00 l1=00 ts=000 capa=50
    [keep] cpu=  1 pk=01 no=00 cl=001(000) l3=001 l2=01 l1=01 ts=000 capa=50
    [keep] cpu=  2 pk=02 no=00 cl=002(000) l3=002 l2=02 l1=02 ts=000 capa=50
    [keep] cpu=  3 pk=03 no=00 cl=003(000) l3=003 l2=03 l1=03 ts=000 capa=50
    CPU clusters:
        0  cpus=  1 cores=  1 capa=50
        1  cpus=  1 cores=  1 capa=50
        2  cpus=  1 cores=  1 capa=50
        3  cpus=  1 cores=  1 capa=50
    
  6. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    Could you also please run a "perf top" so that we have an idea where it's looping ? In case it would be related to a task looping over itself, maybe I'll also ask you to enable task profiling:

    socat /path/to/socket - <<< "set profiling tasks on"
    sleep 10
    socat /path/to/socket - <<< "show profiling tasks"
    
  7. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    Wow, cool, you manage to trigger it with only 4 single-core clusters ? Nice, this should help the local reproduction. I'm currently trying on a 64-core EPYC like you were ;-)

  8. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    Also does your script connect directly to the worker's socket or is it passing the request through the master's socket ?

  9. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor
    PerfTop:    8174 irqs/sec  kernel:45.6%  exact:  0.0% lost: 0/0 drop: 0/0 [4000Hz cycles],  (all, 4 CPUs)
    -------------------------------------------------------------------------------
    
        35.29%  haproxy           [.] _do_poll
         2.91%  [kernel]          [k] entry_SYSCALL_64
         2.05%  [kernel]          [k] pvclock_clocksource_read
         2.05%  [vdso]            [.] 0x000000000000072f
         1.67%  [kernel]          [k] __put_user_nocheck_4
         1.51%  [kernel]          [k] __irqentry_text_start
         1.43%  [kernel]          [k] audit_reset_context
         1.21%  haproxy           [.] fd_update_events
         1.20%  [kernel]          [k] _raw_spin_lock
         1.16%  [kernel]          [k] _raw_write_lock_irq
         1.09%  [kernel]          [k] auditd_test_task
         1.09%  [kernel]          [k] mutex_lock
         0.99%  [kernel]          [k] __rcu_read_unlock
         0.97%  [vdso]            [.] __vdso_clock_gettime
         0.95%  [kernel]          [k] kvm_clock_get_cycles
         0.91%  haproxy           [.] relax_listener
         0.83%  [kernel]          [k] __rcu_read_lock
         0.78%  haproxy           [.] clock_update_local_date
         0.74%  [kernel]          [k] syscall_exit_to_user_mode_prepare
         0.74%  haproxy           [.] run_poll_loop
    
  10. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    Also does your script connect directly to the worker's socket or is it passing the request through the master's socket ?

    Worker socket. The configured one, not /run/haproxy-master.sock

  11. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    Still on -dev8:

    root@n095143:~# ps aux|grep /usr/sbin/haproxy
    root     1727081  0.0  0.0 119068 26172 ?        Ss   09:26   0:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -S /run/haproxy-master.sock -p /run/haproxy.pid
    haproxy  1727083  142  6.1 3149740 2006288 ?     Rl   09:26  34:12 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -S /run/haproxy-master.sock -p /run/haproxy.pid
    
    # gdb -p 1727081 -p 1727083
    ...
    
    (gdb) t a a bt
    
    Thread 4 (Thread 0x7f99b8e236c0 (LWP 1727149) "haproxy"):
    #0  0x00007f99baa5bee6 in epoll_wait (epfd=5482, events=0x7f992c0687d0, maxevents=200, timeout=timeout@entry=74) at ../sysdeps/unix/sysv/linux/epoll_wait.c:30
    #1  0x000055a13291c507 in _do_poll (p=<optimized out>, exp=<optimized out>, wake=<optimized out>) at src/ev_epoll.c:250
    #2  0x000055a132aba3db in run_poll_loop () at src/haproxy.c:2929
    #3  0x000055a132abaab1 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3071
    #4  0x00007f99ba9dc1f5 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
    #5  0x00007f99baa5c89c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
    
    Thread 3 (Thread 0x7f99b96246c0 (LWP 1727148) "haproxy"):
    #0  fd_grab_tgid (desired_tgid=3, fd=<optimized out>) at include/haproxy/fd.h:420
    #1  _do_poll (p=<optimized out>, exp=<optimized out>, wake=<optimized out>) at src/ev_epoll.c:219
    #2  0x000055a132aba3db in run_poll_loop () at src/haproxy.c:2929
    #3  0x000055a132abaab1 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3071
    #4  0x00007f99ba9dc1f5 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
    #5  0x00007f99baa5c89c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
    
    Thread 2 (Thread 0x7f99ba8636c0 (LWP 1727147) "haproxy"):
    #0  0x00007f99baa5bee6 in epoll_wait (epfd=5476, events=0x7f99b4069850, maxevents=200, timeout=timeout@entry=265) at ../sysdeps/unix/sysv/linux/epoll_wait.c:30
    #1  0x000055a13291c507 in _do_poll (p=<optimized out>, exp=<optimized out>, wake=<optimized out>) at src/ev_epoll.c:250
    #2  0x000055a132aba3db in run_poll_loop () at src/haproxy.c:2929
    #3  0x000055a132abaab1 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3071
    #4  0x00007f99ba9dc1f5 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
    #5  0x00007f99baa5c89c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
    
    Thread 1 (Thread 0x7f99ba86f4c0 (LWP 1727083) "haproxy"):
    #0  0x00007ffd68bdfa29 in clock_gettime ()
    #1  0x00007f99baa22439 in __GI___clock_gettime (clock_id=clock_id@entry=3, tp=tp@entry=0x7ffd68b855b0) at ../sysdeps/unix/sysv/linux/clock_gettime.c:42
    #2  0x000055a132b80fda in now_cpu_time () at src/clock.c:92
    #3  clock_entering_poll () at src/clock.c:456
    #4  0x000055a13291c4cc in _do_poll (p=<optimized out>, exp=<optimized out>, wake=<optimized out>) at src/ev_epoll.c:245
    #5  0x000055a132aba3db in run_poll_loop () at src/haproxy.c:2929
    #6  0x000055a132abaab1 in run_thread_poll_loop (data=<optimized out>) at src/haproxy.c:3071
    #7  0x000055a132919035 in main (argc=<optimized out>, argv=<optimized out>) at src/haproxy.c:3661
    
  12. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    OK that allows us to narrow it quite a bit more. I really suspect that an event is being ignored and I don't understand why. And seeing fd_grab_tgid() appear here doesn't amuse me. It's one of the super-sensitive parts of the thread-group code. I'm suspecting that the sharing of outgoing connections between thread groups could have woken up a subtle race. Could you please try with tune.idle-pool.shared off in the global section ? It will stop sharing idle conns between servers and will make sure FDs don't switch from one thread to the other. It's indeed possible that a precise timing happens between the FD used (or released?) by the CLI and one used by an idle conn that changed thread.

  13. idl0r commented on Apr 25, 2025

    @idl0r
    ContributorAuthor

    Had it running till it occurs and then:

    > show profiling tasks
    Tasks activity over 220.599 sec till 0.000 sec ago:
      function                      calls   cpu_tot   cpu_avg   lat_tot   lat_avg
      sc_conn_io_cb+0              587877   167.4ms   284.0ns   298.6ms   507.0ns <- sc_app_chk_rcv_conn@src/stconn.c:843 tasklet_wakeup
      sc_conn_io_cb+0              573015   1.232s    2.149us   630.7ms   1.100us <- sock_conn_iocb@src/sock.c:1094 tasklet_wakeup
      task_run_applet+0            556296   6.974s    12.54us   775.2ms   1.393us <- sc_app_chk_snd_applet@src/stconn.c:1042 appctx_wakeup
      process_chk                   25699   1.072s    41.70us   83.70ms   3.256us <- wake_srv_chk@src/check.c:1089 task_wakeup
      process_stream+0              20293   67.74ms   3.338us   34.24ms   1.687us <- sc_notify@src/stconn.c:1205 task_wakeup
      h1_timeout_task               19712   7.728ms   392.0ns   368.2ms   18.68us <- h1_release@src/mux_h1.c:1382 task_wakeup
      task_run_applet+0             18301   1.376s    75.17us   17.71ms   967.0ns <- sc_app_chk_rcv_applet@src/stconn.c:1022 appctx_wakeup
      process_stream+0              16208   899.6ms   55.50us   128.0ms   7.895us <- stream_new@src/stream.c:583 task_wakeup
      task_process_applet           13458   612.7ms   45.52us   6.614ms   491.0ns <- sc_app_chk_rcv_applet@src/stconn.c:1022 appctx_wakeup
      ssl_sock_io_cb                12759   359.4ms   28.17us   10.17ms   797.0ns <- sock_conn_iocb@src/sock.c:1094 tasklet_wakeup
      srv_chk_io_cb                 12663   51.29ms   4.050us   26.94ms   2.127us <- h1_wake_stream_for_recv@src/mux_h1.c:3614 tasklet_wakeup
      h1_io_cb                      12255   61.83ms   5.045us   4.650ms   379.0ns <- sock_conn_iocb@src/sock.c:1094 tasklet_wakeup
      srv_chk_io_cb                 11780   260.9ms   22.15us   50.13ms   4.255us <- h1_wake_stream_for_send@src/mux_h1.c:3624 tasklet_wakeup
      h1_io_cb                       9757   16.67ms   1.708us   4.264ms   436.0ns <- sock_conn_iocb@src/sock.c:1073 tasklet_wakeup
      task_run_applet+0              9234   120.3ms   13.03us   1.065s    115.4us <- __process_running_peer_sync@src/peers.c:3511 appctx_wakeup
      h1_io_cb                       8134   58.90ms   7.241us   49.73ms   6.113us <- conn_subscribe@src/connection.c:951 tasklet_wakeup
      sc_conn_io_cb+0                6270   104.6ms   16.68us   58.29ms   9.297us <- ssl_sock_io_cb@src/ssl_sock.c:5736 tasklet_wakeup
      sc_conn_io_cb+0                5566   54.91ms   9.864us   2.767ms   497.0ns <- sock_conn_iocb@src/sock.c:1073 tasklet_wakeup
      h1_io_cb                       5377   60.45ms   11.24us   41.11ms   7.645us <- ssl_sock_io_cb@src/ssl_sock.c:5736 tasklet_wakeup
      ssl_sock_io_cb                 5013   162.0ms   32.32us   181.1ms   36.13us <- ssl_sock_start@src/ssl_sock.c:4976 tasklet_wakeup
      ssl_sock_io_cb                 4857   65.55ms   13.49us   5.633ms   1.159us <- sock_conn_iocb@src/sock.c:1073 tasklet_wakeup
      process_stream+0               2617   14.01ms   5.354us   11.03ms   4.213us <- run_tasks_from_lists@src/task.c:667 task_queue
      task_run_applet+0              2367   24.16ms   10.21us   135.2ms   57.10us <- __process_running_peer_sync@src/peers.c:3538 appctx_wakeup
      process_stream+0               2331   3.424ms   1.468us   2.843ms   1.219us <- sc_app_chk_snd_conn@src/stconn.c:914 task_wakeup
      sc_conn_io_cb+0                1686   17.37ms   10.30us   2.097ms   1.243us <- h1_wake_stream_for_recv@src/mux_h1.c:3614 tasklet_wakeup
      process_table_expire            900   6.669ms   7.410us   3.250ms   3.610us <- run_tasks_from_lists@src/task.c:667 task_queue
      task_run_applet+0               718   2.279ms   3.173us   36.13ms   50.33us <- peer_session_create@src/peers.c:3272 appctx_wakeup
      task_run_applet+0               362   342.2us   945.0ns   10.83ms   29.93us <- sc_app_shut_applet@src/stconn.c:975 appctx_wakeup
      main+0x12aab0                   338   4.792ms   14.18us   1.768ms   5.231us <- ssl_sock_io_cb@src/ssl_sock.c:5736 tasklet_wakeup
      main+0x12aab0                   338   339.0us   1.003us   2.039ms   6.031us <- spop_conn_restart_reading@src/mux_spop.c:573 tasklet_wakeup
      task_process_applet             287   89.75ms   312.7us   606.6us   2.113us <- sc_applet_create@src/stconn.c:573 appctx_wakeup
      task_process_applet             272   83.34ms   306.4us   180.4us   663.0ns <- sc_app_chk_snd_applet@src/stconn.c:1042 appctx_wakeup
      task_process_applet             268   355.1us   1.324us   12.35ms   46.09us <- spoe_stop_processing@src/flt_spoe.c:946 appctx_wakeup
      process_peer_sync               252   9.084ms   36.05us   16.50ms   65.47us <- stktable_touch_with_exp@src/stick_table.c:661 task_wakeup
      srv_cleanup_toremove_conns      226   11.92ms   52.76us   3.927ms   17.38us <- srv_cleanup_idle_conns@src/server.c:7213 task_wakeup
      srv_chk_io_cb                   220   201.7us   916.0ns   9.885ms   44.93us <- ssl_sock_io_cb@src/ssl_sock.c:5736 tasklet_wakeup
      process_peer_sync               200   3.554ms   17.77us   4.660ms   23.30us <- __peer_session_deinit@src/peers.c:1058 task_wakeup
      sc_conn_io_cb+0                 174   3.837ms   22.05us   479.6us   2.756us <- h1_wake_stream_for_send@src/mux_h1.c:3624 tasklet_wakeup
      srv_cleanup_idle_conns          167   1.455ms   8.715us   459.1us   2.749us <- run_tasks_from_lists@src/task.c:667 task_queue
      process_chk                     136   8.209ms   60.36us   179.5us   1.320us <- run_tasks_from_lists@src/task.c:667 task_queue
      process_stream+0                134   11.94ms   89.08us   161.6us   1.205us <- spoe_handle_receiving_frame_appctx@src/flt_spoe.c:478 task_wakeup
      main+0x12aab0                   134   40.98us   305.0ns   1.036ms   7.730us <- spop_do_shutw@src/mux_spop.c:3087 tasklet_wakeup
      task_process_applet             134   163.2us   1.217us   16.75ms   125.0us <- spoe_init_appctx@src/flt_spoe.c:402 appctx_wakeup
      sc_conn_io_cb+0                 134   105.3us   786.0ns   46.45us   346.0ns <- spop_strm_notify_recv@src/mux_spop.c:952 tasklet_wakeup
      h2_io_cb                        131   849.9us   6.487us   2.682ms   20.48us <- h2c_restart_reading@src/mux_h2.c:1003 tasklet_wakeup
      h2_io_cb                        121   3.681ms   30.42us   379.4us   3.135us <- ssl_sock_io_cb@src/ssl_sock.c:5736 tasklet_wakeup
      sc_conn_io_cb+0                 102   1.095ms   10.73us   73.50us   720.0ns <- spop_strm_notify_send@src/mux_spop.c:965 tasklet_wakeup
      main+0x1230e0                   101   103.0us   1.019us   8.451ms   83.67us <- spop_release@src/mux_spop.c:752 task_wakeup
      srv_chk_io_cb                    95   964.5us   10.15us   120.5us   1.268us <- sock_conn_iocb@src/sock.c:1094 tasklet_wakeup
      h2_io_cb                         90   28.86us   320.0ns   4.906ms   54.52us <- h2_snd_buf@src/mux_h2.c:7801 tasklet_wakeup
      task_process_applet              85   56.84us   668.0ns   1.921ms   22.60us <- sc_app_shut_applet@src/stconn.c:975 appctx_wakeup
      accept_queue_process+0           85   435.8us   5.126us   5.937ms   69.85us <- listener_accept@src/listener.c:1492 tasklet_wakeup
      xprt_handshake_io_cb             53   452.2us   8.531us   242.1us   4.568us <- xprt_handshake_start@src/xprt_handshake.c:140 tasklet_wakeup
      h2_timeout_task                  39   50.49us   1.294us   1.683ms   43.15us <- h2_release@src/mux_h2.c:1446 task_wakeup
      process_peer_sync                39   1.531ms   39.27us   98.45us   2.524us <- run_tasks_from_lists@src/task.c:667 task_queue
      h1_timeout_task                  39   1.409ms   36.14us   219.0us   5.615us <- h1_init@src/mux_h1.c:1315 task_queue
      task_run_applet+0                33   3.675ms   111.4us   127.8us   3.872us <- sc_applet_create@src/stconn.c:573 appctx_wakeup
      main+0x12aab0                    32   12.18us   380.0ns   85.66us   2.676us <- spop_snd_buf@src/mux_spop.c:3387 tasklet_wakeup
      h1_io_cb                         31   64.55us   2.082us   15.38us   496.0ns <- xprt_handshake_io_cb@src/xprt_handshake.c:92 tasklet_wakeup
      srv_chk_io_cb                    22   15.68us   712.0ns   4.779us   217.0ns <- xprt_handshake_io_cb@src/xprt_handshake.c:92 tasklet_wakeup
      xprt_handshake_io_cb             22   264.7us   12.03us   8.828us   401.0ns <- sock_conn_iocb@src/sock.c:1073 tasklet_wakeup
      ssl_sock_io_cb                   12   3.791us   315.0ns   20.05us   1.670us <- conn_subscribe@src/connection.c:951 tasklet_wakeup
      task_run_applet+0                10   67.40us   6.739us   32.24us   3.224us <- sync_peer_app_state@src/peers.c:3399 appctx_wakeup
      process_peer_sync                 9   134.4us   14.94us   18.70us   2.077us <- peer_io_handler@src/peers.c:3057 task_wakeup
      process_peer_sync                 5   97.34us   19.47us   31.42us   6.284us <- init_connected_peer@src/peers.c:2860 task_wakeup
      h2_timeout_task                   2   38.92us   19.46us   1.480us   740.0ns <- h2c_update_timeout@src/mux_h2.c:924 task_queue
      h2_io_cb                          1   469.0ns   469.0ns   400.0ns   400.0ns <- h2_timeout_task@src/mux_h2.c:5141 tasklet_wakeup
      process_table_expire              1   70.66us   70.66us   250.0ns   250.0ns <- stktable_requeue_exp@src/stick_table.c:743 task_queue
      h2_timeout_task                   1   78.15us   78.15us   260.0ns   260.0ns <- run_tasks_from_lists@src/task.c:667 task_queue
    
  14. 28 remaining items

  15. added
    3.1This issue affects the HAProxy 3.1 stable branch. (EOL)
    on Apr 25, 2025
  16. rnsanchez commented on Apr 25, 2025

    @rnsanchez
    Contributor

    Hi Willy,

    Any chance this patch might help #2937? We have a few instances (maybe most!) that use shards.

  17. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    Hi Ricardo!

    Maybe I misunderstood it but my understanding was that it was wasting CPU in the stick-table index update. Olivier is currently working on this to offload the lock to a task and the gains he observed are already very good (but we suspect we'll then discover the net bottleneck); hopefully early next week we'll merge his patches. However if you're experiencing cases where the CLI freezes, that's different, but I have not understood that in the description.

  18. rnsanchez commented on Apr 25, 2025

    @rnsanchez
    Contributor

    My question is mostly because during the degradation (loop), we also lose observability:

    #2937 (comment)

    Given our rate of CLI interactions (stats monitoring which does not keep reconnecting, and our socket-watchdog that reconnects every 500ms), there is the possibility that we could get both issues to trigger, together. Or not. :-)

  19. wtarreau commented on Apr 25, 2025

    @wtarreau
    Member

    I got it but I didn't understand if that was caused by the long time to get the stick-table lock or by anything else. In the traces at least the lock was keeping something like half of the threads busy, which can already be a concern. But you could be right, maybe you were hit by the same bug! Socat has a default timeout of 0.5s so if haproxy was stuck in a CPU loop for that long, socat could have timed out. Using -t you can increase it (socat -t 5 ...), and it will confirm whether it was a lock or the CLI's listener. The lock cannot hold much more than one second without triggering the watchdog, so that would help sort the issue.

    In any case, the bug above is horrible, and if you're running with thread groups, I strongly encourage you to pick the patch (or just to update to latest master, because aside this bug it's getting really clean).

  20. idl0r commented on Apr 28, 2025

    @idl0r
    ContributorAuthor

    Ah got it! And it can trivially be reproduced with bind ... shards 1 on a line. It just happens that since the introduction of group-based shards, we now use them by default and there's no bounding between groups by default outside of the stats socket. I suspect that your script might re-establish a connection just before finishing consuming the old one, leaving a short window where a connection still exists, encouraging the accept's load balancing to bounce the connection to another thread. The code just forgets to transfer the nbconn when switching to another group (needed because technically speaking it's another listener).

    Now I can't break it anymore (including in http with shards 1). I've just merged the patch above (f1064c7). Christian, many thanks once again for this great observation and all the details. It could have lived long without your precious help!

    Oh, neat! Thanks! Will try that patch today.

  21. idl0r commented on Apr 28, 2025

    @idl0r
    ContributorAuthor

    Looks very good at the first glance, @wtarreau :)

  22. idl0r commented on Apr 28, 2025

    @idl0r
    ContributorAuthor

    Running fine for some hours already. So yeah, I think that's it.

  23. removed
    3.0This issue affects the HAProxy 3.0 stable branch.
    3.1This issue affects the HAProxy 3.1 stable branch. (EOL)
    on May 20, 2025
  24. removed
    2.8This issue affects the HAProxy 2.8 stable branch.
    on May 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: fixedThis issue is a now-fixed bug.subsystem: coreThe issue is within the core of haproxy.type: bugThis issue describes a bug.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions