There's a lot more happening under the covers than just a SIGHUP. For example, closing the terminal window also causes the pty to be closed, so any output or input will return I/O errors.
We can see this by running strace on the bash process when you close the window.
We start with the bash process waiting at the prompt (the pselect()) and then close the window...
% strace -p 1090 strace: Process 1090 attached pselect6(1, [0], NULL, NULL, NULL, {[], 8}) = ? ERESTARTNOHAND (To be restarted if no handler) --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=3409, si_uid=500} --- --- SIGCONT {si_signo=SIGCONT, si_code=SI_KERNEL} --- rt_sigreturn({mask=[]}) = -1 EINTR (Interrupted system call) ioctl(2, TCXONC, TCOON) = -1 EIO (Input/output error) ioctl(0, TCGETS, 0x7ffe1d1734e0) = -1 EIO (Input/output error) ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = -1 EIO (Input/output error)
We're starting to see the I/O errors as bash tries to process the handler...
At this point notice that bash decided to shutdown because it has no control terminal, so it restores all the signal handlers and sends itself another SIGHUP
rt_sigaction(SIGINT, {sa_handler=0x467410, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, {sa_handler=0x4bb540, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, 8) = 0 rt_sigaction(SIGTERM, {sa_handler=0x466f10, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7fe5c31b3060}, {sa_handler=0x4bb540, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, 8) = 0 rt_sigaction(SIGHUP, {sa_handler=0x4640e0, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, {sa_handler=0x4bb540, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, 8) = 0 rt_sigaction(SIGALRM, {sa_handler=0x4676d0, sa_mask=[HUP INT ILL TRAP ABRT BUS FPE USR1 SEGV USR2 PIPE ALRM TERM XCPU XFSZ VTALRM SYS], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, {sa_handler=0x4bb540, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, 8) = 0 rt_sigaction(SIGWINCH, {sa_handler=0x466f00, sa_mask=[], sa_flags=SA_RESTORER, sa_restorer=0x7fe5c31b3060}, {sa_handler=0x4baaa0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7fe5c31b3060}, 8) = 0 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 getpid() = 1090 kill(1090, SIGHUP) = 0 --- SIGHUP {si_signo=SIGHUP, si_code=SI_USER, si_pid=1090, si_uid=500} ---
And then the close down process continues (rewriting .bash_history and so on).
So it's not the initial SIGHUP that terminates the shell, it's the loss of the pty providing a terminal for input.