peak / s5cmd

Parallel S3 and local filesystem execution tool.
MIT License
2.72k stars 242 forks source link

Correct exit codes for SIGINT signals #615

Open sonmezonur opened 1 year ago

sonmezonur commented 1 year ago

Currently s5cmd does not return proper exit codes if we terminate the process with control c.

s5cmd ls 's3://backups/*'
^C
❯ echo $?
0
s5cmd cp 's3://backups/*' 'dir/'
^C
❯ echo $?
1

ls returns success while cp returns with exit code 1. Exit codes for all commands should be consistent.

Maybe we should return 130 since most of the cli tools exit with 130 if the process is canceled by the user.

dzuelke commented 8 months ago

Returning 130 is not the correct behavior. What you have to do is terminate yourself (the current PID) using the INT signal.

SIGINT has the integer value 2 on basically all systems, and the shell represents the termination signal using exit code 128+$signal. That's why if you terminate a program, its exit status will usually say "143" on the shell - SIGTERM has integer value 15.

But there is a difference between exiting with a status code, and exiting in response to a signal. The calling program can determine the difference, using e.g. WIFEXITED and WIFSIGNALED and act accordingly.

Specifically, shells, when they themselves receive a SIGINT, will wait and see what their child processes do. Ctrl+C is sent to the entire foreground process loop, so if a child exits e.g. 0 or 1, then the shell will think "oh, ok, did not react to the signal". When, on the other hand, the child terminates itself using an INT signal, the shell will know "ah, time to also react to the interrupt".

Concrete example: while true; do date; done lets you Ctrl+C out, because date does the right thing and kills itself with INT, upon which the shell also terminates the loop.

If you while true; ping google.com; sleep 0.1; done instead, you can't get out of the loop - every Ctrl+C causes a new iteration, because ping exits with 0 on SIGINT. To save you some frustration, I added the sleep 0.1 so that you can spam Ctrl+C until the shell catches it in between ping invocations and terminates the loop ;)

Writeup here: https://www.cons.org/cracauer/sigint.html