This was because at the point at which exit is called, we can only free a
t_simple_cmd, but not the whole t_cmd tree. This commit introduces a convention
of returning a t_subprocess enum from each function in exec. If the current
thread is a subprocess, SUBPROCESS is returned, else PARENTPROCESS. We also no
longer call exit in subproceses. This way, all processes bubble up to main,
where if SUBPROCESS is returned, all memory is freed and the program exits.
This also removes the previous should_exit convention.
Still TODO: handling of the exit builtin, which should also bubble up in the
same way.
$ touch cat
$ unset PATH
$ cat
m==75845== Memcheck, a memory error detector
==75845== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==75845== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==75845== Command: ./minishell
==75845==
==75846== Memcheck, a memory error detector
==75846== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==75846== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyright info
==75846== Command: /nix/store/6wgd8c9vq93mqxzc7jhkl86mv6qbc360-coreutils-9.5/bin/touch cat
==75846==
==75846==
==75846== FILE DESCRIPTORS: 0 open (0 std) at exit.
==75846==
==75846== HEAP SUMMARY:
==75846== in use at exit: 0 bytes in 0 blocks
==75846== total heap usage: 46 allocs, 46 frees, 8,126 bytes allocated
==75846==
==75846== All heap blocks were freed -- no leaks are possible
==75846==
==75846== For lists of detected and suppressed errors, rerun with: -s
==75846== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
minishell: cat: Permission denied
==75849==
==75849== FILE DESCRIPTORS: 3 open (3 std) at exit.
==75849==
==75849== HEAP SUMMARY:
==75849== in use at exit: 4,181 bytes in 12 blocks
==75849== total heap usage: 982 allocs, 970 frees, 122,299 bytes allocated
==75849==
==75849== 8 bytes in 1 blocks are definitely lost in loss record 1 of 9
==75849== at 0x48467D9: malloc (in /nix/store/phbnjdfmy3v4ak9xf211y2336mv5kx9s-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75849== by 0x113C22: ft_calloc (ft_calloc.c:28)
==75849== by 0x112399: get_paths_array (src/subst/simple_filename_exp.c:37)
==75849== by 0x1121EE: filepath_from_env (src/subst/simple_filename_exp.c:144)
==75849== by 0x1121C0: get_cmdpath (src/subst/simple_filename_exp.c:184)
==75849== by 0x10CD97: exec_external_cmd (src/executing/simple_cmd/simple_cmd_execute.c:67)
==75849== by 0x10CC58: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:94)
==75849== by 0x10B12C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==75849== by 0x10A4FD: execute_command (src/minishell.c:37)
==75849== by 0x10A3B2: main (src/minishell.c:90)
==75849==
==75849== 24 bytes in 1 blocks are still reachable in loss record 6 of 9
==75849== at 0x48467D9: malloc (in /nix/store/phbnjdfmy3v4ak9xf211y2336mv5kx9s-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75849== by 0x113C22: ft_calloc (ft_calloc.c:28)
==75849== by 0x10D4A9: cmd_create (src/parser/cmd/cmd.c:20)
==75849== by 0x10F6A1: simple_cmd_create (src/parser/simple_cmd/simple_cmd_parse.c:24)
==75849== by 0x10F4E4: minishell_simple_cmd_parse (src/parser/simple_cmd/simple_cmd_parse.c:38)
==75849== by 0x10E078: minishell_group_or_simple_parse (src/parser/group_cmd/group_cmd_parse.c:53)
==75849== by 0x10E4AC: minishell_pipeline_parse (src/parser/pipeline/pipeline_parse.c:26)
==75849== by 0x10D93C: minishell_cmds_parse (src/parser/cmd/cmds_parse.c:30)
==75849== by 0x1139D5: minishell_parse (src/parser/cmd_parsing.c:67)
==75849== by 0x10A38B: main (src/minishell.c:87)
==75849==
==75849== LEAK SUMMARY:
==75849== definitely lost: 8 bytes in 1 blocks
==75849== indirectly lost: 0 bytes in 0 blocks
==75849== possibly lost: 0 bytes in 0 blocks
==75849== still reachable: 24 bytes in 1 blocks
==75849== suppressed: 4,149 bytes in 10 blocks
==75849==
==75849== For lists of detected and suppressed errors, rerun with: -s
==75849== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
126
==75845==
==75845== FILE DESCRIPTORS: 3 open (3 std) at exit.
==75845==
==75845== HEAP SUMMARY:
==75845== in use at exit: 4,201 bytes in 14 blocks
==75845== total heap usage: 844 allocs, 830 frees, 72,248 bytes allocated
==75845==
==75845== 8 bytes in 1 blocks are definitely lost in loss record 1 of 8
==75845== at 0x48467D9: malloc (in /nix/store/phbnjdfmy3v4ak9xf211y2336mv5kx9s-valgrind-3.23.0/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==75845== by 0x113C22: ft_calloc (ft_calloc.c:28)
==75845== by 0x112399: get_paths_array (src/subst/simple_filename_exp.c:37)
==75845== by 0x1121EE: filepath_from_env (src/subst/simple_filename_exp.c:144)
==75845== by 0x1121C0: get_cmdpath (src/subst/simple_filename_exp.c:184)
==75845== by 0x10CD97: exec_external_cmd (src/executing/simple_cmd/simple_cmd_execute.c:67)
==75845== by 0x10CC58: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:94)
==75845== by 0x10B12C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==75845== by 0x10A4FD: execute_command (src/minishell.c:37)
==75845== by 0x10A3B2: main (src/minishell.c:90)
==75845==
==75845== LEAK SUMMARY:
==75845== definitely lost: 8 bytes in 1 blocks
==75845== indirectly lost: 0 bytes in 0 blocks
==75845== possibly lost: 0 bytes in 0 blocks
==75845== still reachable: 0 bytes in 0 blocks
==75845== suppressed: 4,193 bytes in 13 blocks
==75845==
==75845== For lists of detected and suppressed errors, rerun with: -s
==75845== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)inishell: cat: Permission denied
debug notes:
$ cat << eof > /root/outfile
hello
eof
minishell: open: Permission denied
minishell: hello: command not found
==42382==
==42382== FILE DESCRIPTORS: 9 open (3 std) at exit.
==42382== Open file descriptor 8: /dev/pts/3
==42382== at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382== by 0x10C9CC: handle_redirections (src/executing/simple_cmd/handle_redirections.c:65)
==42382== by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382== by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382== by 0x10A4DD: execute_command (src/minishell.c:37)
==42382== by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 7: /dev/pts/3
==42382== at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382== by 0x10C9B9: handle_redirections (src/executing/simple_cmd/handle_redirections.c:64)
==42382== by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382== by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382== by 0x10A4DD: execute_command (src/minishell.c:37)
==42382== by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 6: /dev/pts/3
==42382== at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382== by 0x10C9CC: handle_redirections (src/executing/simple_cmd/handle_redirections.c:65)
==42382== by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382== by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382== by 0x10A4DD: execute_command (src/minishell.c:37)
==42382== by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 5: /dev/pts/3
==42382== at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382== by 0x10C9B9: handle_redirections (src/executing/simple_cmd/handle_redirections.c:64)
==42382== by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382== by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382== by 0x10A4DD: execute_command (src/minishell.c:37)
==42382== by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 4: /dev/pts/3
==42382== at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382== by 0x10C9A6: handle_redirections (src/executing/simple_cmd/handle_redirections.c:63)
==42382== by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382== by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382== by 0x10A4DD: execute_command (src/minishell.c:37)
==42382== by 0x10A3A2: main (src/minishell.c:89)
==42382==
==42382== Open file descriptor 3: /tmp/minishell_here_doc_78Ak8J9TeVu (deleted)
==42382== at 0x49A8C1B: dup (in /nix/store/nqb2ns2d1lahnd5ncwmn6k84qfd7vx2k-glibc-2.40-36/lib/libc.so.6)
==42382== by 0x10C9A6: handle_redirections (src/executing/simple_cmd/handle_redirections.c:63)
==42382== by 0x10CBF6: simple_cmd_execute (src/executing/simple_cmd/simple_cmd_execute.c:91)
==42382== by 0x10B10C: cmd_execute (src/executing/cmd/cmd_execute.c:23)
==42382== by 0x10A4DD: execute_command (src/minishell.c:37)
==42382== by 0x10A3A2: main (src/minishell.c:89)
debug notes:
++++++++++++++++++++++++++++++++++++++++++++++++++++
failed: ambiguous redirect
++++++++++++++++++++++++++++++++++++++++++++++++++++
++++ test input:
export target="outfile1 outfile2"
echo hello > $target
echo $?
echo hi >> $target
echo $?
cat < $target
echo $?
ls
echo $?
++++ Got output:
hello
0
hi
0
echo $?
ls
echo $?
++++ But expected:
minishell: $target: ambiguous redirect
1
minishell: $target: ambiguous redirect
1
minishell: $target: ambiguous redirect
1
0
Reproduced this with rr record --cahos, see
/home/khais/.local/share/rr/minishell-48
$ export target="outfile1 outfile2"
$ echo hi > $target
hi
Break in simple_cmd_execute, second command has no redirections when it should
have some, presumably this comes from some uninitialized memory somewhere.
This caused redirections to keep stdout redirected to the outfile, which caused
problems with displaying the prmpt.
The shell hangs, but exits with C-d
Builtins affected:
echo hi > outfile
pwd > outfile
env > outfile