Particularly cleanly deinit() after a configuration check to clean up the output of valgrind which reports "possible losses" without a deinit() and does not with a deinit(), converting actual losses into proper hard losses which makes the whole stuff easier to analyze.
As an example, given an example configuration of the following: frontend foo bind *:8080 mode http Running `haproxy -c -f cfg` within valgrind will report 4 possible losses: $ valgrind --leak-check=full ./haproxy -c -f ./example.cfg ==21219== Memcheck, a memory error detector ==21219== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==21219== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==21219== Command: ./haproxy -c -f ./example.cfg ==21219== [WARNING] 165/001100 (21219) : config : missing timeouts for frontend 'foo'. | While not properly invalid, you will certainly encounter various problems | with such a configuration. To fix this, please ensure that all following | timeouts are set to a non-zero value: 'client', 'connect', 'server'. Warnings were found. Configuration file is valid ==21219== ==21219== HEAP SUMMARY: ==21219== in use at exit: 1,436,631 bytes in 130 blocks ==21219== total heap usage: 153 allocs, 23 frees, 1,447,758 bytes allocated ==21219== ==21219== 7 bytes in 1 blocks are possibly lost in loss record 5 of 54 ==21219== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==21219== by 0x5726489: strdup (strdup.c:42) ==21219== by 0x468FD9: bind_conf_alloc (listener.h:158) ==21219== by 0x468FD9: cfg_parse_listen (cfgparse-listen.c:557) ==21219== by 0x459DF3: readcfgfile (cfgparse.c:2167) ==21219== by 0x5056CD: init (haproxy.c:2021) ==21219== by 0x418232: main (haproxy.c:3121) ==21219== ==21219== 14 bytes in 1 blocks are possibly lost in loss record 9 of 54 ==21219== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==21219== by 0x5726489: strdup (strdup.c:42) ==21219== by 0x468F9B: bind_conf_alloc (listener.h:154) ==21219== by 0x468F9B: cfg_parse_listen (cfgparse-listen.c:557) ==21219== by 0x459DF3: readcfgfile (cfgparse.c:2167) ==21219== by 0x5056CD: init (haproxy.c:2021) ==21219== by 0x418232: main (haproxy.c:3121) ==21219== ==21219== 128 bytes in 1 blocks are possibly lost in loss record 35 of 54 ==21219== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==21219== by 0x468F90: bind_conf_alloc (listener.h:152) ==21219== by 0x468F90: cfg_parse_listen (cfgparse-listen.c:557) ==21219== by 0x459DF3: readcfgfile (cfgparse.c:2167) ==21219== by 0x5056CD: init (haproxy.c:2021) ==21219== by 0x418232: main (haproxy.c:3121) ==21219== ==21219== 608 bytes in 1 blocks are possibly lost in loss record 46 of 54 ==21219== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==21219== by 0x4B953A: create_listeners (listener.c:576) ==21219== by 0x4578F6: str2listener (cfgparse.c:192) ==21219== by 0x469039: cfg_parse_listen (cfgparse-listen.c:568) ==21219== by 0x459DF3: readcfgfile (cfgparse.c:2167) ==21219== by 0x5056CD: init (haproxy.c:2021) ==21219== by 0x418232: main (haproxy.c:3121) ==21219== ==21219== LEAK SUMMARY: ==21219== definitely lost: 0 bytes in 0 blocks ==21219== indirectly lost: 0 bytes in 0 blocks ==21219== possibly lost: 757 bytes in 4 blocks ==21219== still reachable: 1,435,874 bytes in 126 blocks ==21219== suppressed: 0 bytes in 0 blocks ==21219== Reachable blocks (those to which a pointer was found) are not shown. ==21219== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==21219== ==21219== For counts of detected and suppressed errors, rerun with: -v ==21219== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0) Re-running the same command with the patch applied will not report any losses any more: $ valgrind --leak-check=full ./haproxy -c -f ./example.cfg ==22124== Memcheck, a memory error detector ==22124== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==22124== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info ==22124== Command: ./haproxy -c -f ./example.cfg ==22124== [WARNING] 165/001503 (22124) : config : missing timeouts for frontend 'foo'. | While not properly invalid, you will certainly encounter various problems | with such a configuration. To fix this, please ensure that all following | timeouts are set to a non-zero value: 'client', 'connect', 'server'. Warnings were found. Configuration file is valid ==22124== ==22124== HEAP SUMMARY: ==22124== in use at exit: 313,864 bytes in 82 blocks ==22124== total heap usage: 153 allocs, 71 frees, 1,447,758 bytes allocated ==22124== ==22124== LEAK SUMMARY: ==22124== definitely lost: 0 bytes in 0 blocks ==22124== indirectly lost: 0 bytes in 0 blocks ==22124== possibly lost: 0 bytes in 0 blocks ==22124== still reachable: 313,864 bytes in 82 blocks ==22124== suppressed: 0 bytes in 0 blocks ==22124== Reachable blocks (those to which a pointer was found) are not shown. ==22124== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==22124== ==22124== For counts of detected and suppressed errors, rerun with: -v ==22124== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) It might be worth investigating what exactly HAProxy does to lose pointers to the start of those 4 memory areas and then to be able to still free them during deinit(). If HAProxy is able to free them, they ideally should be "still reachable" and not "possibly lost". --- src/haproxy.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/haproxy.c b/src/haproxy.c index 2250815b3..6548db6b5 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2202,7 +2202,7 @@ static void init(int argc, char **argv) if (pr || px) { /* At least one peer or one listener has been found */ qfprintf(stdout, "Configuration file is valid\n"); - exit(0); + deinit_and_exit(0); } qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n"); exit(2); @@ -3770,10 +3770,7 @@ int main(int argc, char **argv) run_thread_poll_loop(0); #endif - /* Do some cleanup */ - deinit(); - - exit(0); + deinit_and_exit(0); } #if defined(__clang_version__) -- 2.27.0