Pressing Ctrl+C in a terminal sends the SIGINT signal to the process running in the terminal. (More precisely, to all processes in the foreground process group; for example, if you're running
foo | tail -f then the signal is sent to both
The conventional meaning of SIGINT (INTerrupt signal) is “abort the current task and return to an interactive prompt”. Programs that don't have an interactive prompt, such as tail, simply exit to let the shell take over.
trap command defines the shell's behavior when it receives a signal. For example
trap 'echo killed' INT makes the shell print
killed when it receives a SIGINT signal.
trap 'echo killed' 2 is the same on a Linux PC because 2 is the number of the signal whose name is INT. This only triggers if the shell gets the signal, it doesn't trigger if another program is in the foreground.
trap "" INT is a special case. It doesn't just tell the shell to do nothing when it receives the signal, it tells the shell to ignore the signal. When a process registers a handler for a signal, that doesn't affect the programs it runs — the handler is code in the process, there would be no way to invoke it from another program. But ignoring a signal is a different setting, and that one is kept when a program runs another program. So after
trap "" INT, when you run
tail, the signal is still ignored, and pressing Ctrl+C has no effect.
If you want to keep effectively ignoring signals in the shell but not in programs that it starts, set a non-empty trap, for example
trap " " INT or
trap : INT (
: is the shell's no-op command). Alternatively, run
trap - INT before running
tail to reset the signal handling to its default non-ignored state.