Introduction to Linux Signals 101

Posted by cas on Jul 3rd, 2008
2008
Jul 3

or

^C doesn’t kill processes, SIGINT does

On the LUV mailing list recently, the perils of tty handling when booting with “init=/bin/bash” came up, and somebody asked why running ‘ping’ (without remembering to run stty or openvt first) will result in you having to reboot.

i.e. “why doesn’t ^C work in emergency mode”?

I wrote a fairly detailed, but comprehensible to a novice, answer and a friend suggested i should have written it as a blog post – which was the point of me setting up a blog in the first place.

So here’s a slightly edited version of it:

> Couldn’t you just open another console, run “top” and find the PID for
> ping and kill it? Or ps aux |grep ping and kill it? Is a reboot the
> only way to kill a ping where ^C is not available?

there’s nothing special about ^C except that by long convention it is mapped to the interrupt signal aka intr aka SIGINT. So, ^C itself doesn’t kill a program, the fact that it generates an interrupt signal does.

If you’ve rebooted for emergency maintenance (e.g. “init=/bin/bash” on the LILO or GRUB command line) then all you get is ONE instance of /bin/bash. Nothing else is running and nothing else has been run (because you’ve overriden the usual init with /bin/bash). No setup has been done on the terminal, and no other virtual terminals have been opened. The emergency environment is minimal (and deliberately so – you asked for it, you got it). It’s up to you to do whatever is needed to set up the environment so that you can do the required maintenance/repair work.

So if you run ping *before* remembering to set up the terminal (‘stty sane’) then ^C doesn’t work because ^C doesn’t generate SIGINT so there’s no way of telling ping to quit, and if you haven’t opened another virtual terminal with openvt (aka “open” – it got renamed some time ago) then there is no other shell available to run top or ps or kill.

BTW, it’s not just ping. You’ll see the same problem in the same environment with ANY program that runs continuously until it gets a signal to terminate it. ping’s just the most obvious and common example.

Most programs, especially simple programs like ping, don’t have a ^C handler. They don’t need one. They have a signal handler which, amongst other things, handles SIGINT however it’s generated – it can be generated by pressing ^C in a normal tty environment, or by sending the program a SIGINT (e.g. “kill -2″).

That, BTW, is a core difference between a SIGTERM (just plain ‘kill’ or ‘kill -15′) and SIGKILL (‘kill -9′).

SIGTERM is usually handled by the program by setting up a signal handler for it, and it voluntarily terminates when it receives the signal (usually cleaning up, closing files, etc before it does so). If the program hasn’t set up a handler for SIGTERM then the default action is to just terminate. A program can set up a handler which does nothing on SIGTERM, which effectively just ignores the signal.

SIGKILL is handled by the kernel and it just kills the process immediately – it can not be blocked or intercepted by the program.

(By common convention, SIGHUP or ‘kill -1′ tells a long running daemon process to just reload it’s config files. It’s also generated when the tty that the program is running on is terminated – e.g. you log out or the modem hangs up or the ssh session dies, hence the name “HUP” aka “HANGUP”. That’s why you need to use something like nohup or screen if you want a program to continue running after you log out)

In a way, ‘kill’ is a bit of a misnomer. It’s actually a generic tool for sending signals to running processes, but the default action for most of those signals is to terminate the program. Here’s a list of the signals which can be sent.

$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL
 5) SIGTRAP	 6) SIGABRT	 7) SIGBUS	 8) SIGFPE
 9) SIGKILL	10) SIGUSR1	11) SIGSEGV	12) SIGUSR2
13) SIGPIPE	14) SIGALRM	15) SIGTERM	16) SIGSTKFLT
17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU
25) SIGXFSZ	26) SIGVTALRM	27) SIGPROF	28) SIGWINCH
29) SIGIO	30) SIGPWR	31) SIGSYS	34) SIGRTMIN
35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3	38) SIGRTMIN+4
39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12
47) SIGRTMIN+13	48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14
51) SIGRTMAX-13	52) SIGRTMAX-12	53) SIGRTMAX-11	54) SIGRTMAX-10
55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7	58) SIGRTMAX-6
59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX

See the man pages for init(8), kill(1), and especially signal(7) for more info on this topic.

fixed-width style sheets suck

Posted by cas on May 7th, 2008
2008
May 7

I’m getting more and more annoyed by web sites that have style-sheets with tiny little fonts and widths specified in pixels rather than percentages (or ‘em’ units).

Almost every web site i visit these days seems to have a style sheet written by some idiot who thinks “if it looks good on my screen using my eyes then it’s perfect for everyone”.

WRONG

Specifying widths in pixels is NOT for text. It’s for images, you morons.

Continue Reading »

poll: package my vhosting system for debian?

Posted by cas on Apr 29th, 2008
2008
Apr 29

There was a discussion today on the LUV-main mailing list about apache virtual hosting. Someone suggested mod_vhost_alias which is OK for a simple solution, but pretty limited.

IMO, there are much better ways of doing it. Specifically, generating config fragments for each virtual host.

I wrote such a system years ago, and have always thought “I should package it up for debian”. There’s a moderate amount of work involved in doing so, and probably an even larger amount of support work afterwards. Worst of all, I’d have to write – or con someone else into writing – documentation for it (it’s easy enough to use that you can be SHOWN how to use it in 10 minutes, but that isn’t good enough for a distributed package).

I guess the point of this blog post is to find out if there’s sufficient interest to make it worth the effort. Feel free to comment or email me about it.

Continue Reading »

Keeping apt archives empty…or not.

Posted by cas on Apr 26th, 2008
2008
Apr 26

In this post, Steven Hanley wonders how to keep /var/cache/apt/archives empty on a machine that has a full mirror of debian on it.

That’s actually the wrong question.

The right question is ‘Why is /var/cache/apt/archives even relevant on a machine with a full mirror of debian?’

/etc/apt/sources.list has always supported file:/ URLs. for example, sources.list on my local debian mirror looks like this:

deb file:/home/ftp/debian unstable main contrib non-free
deb file:/home/ftp/debian-multimedia/ unstable main

With a file URL, apt-get doesn’t need to download any packages, and thus doesn’t need to cache anything in /var/cache/apt/archives. No need to keep it empty, it just is empty.

In a related post, Andrew Pollock suggests adding DPkg::Post-Invoke { “apt-get clean”; }; to /etc/apt/apt.conf.

That would be fine if you ONLY ever ran “apt-get update ; apt-get dist-upgrade”.

It’s not fine if you run “apt-get -d” to download packages first, then install a few packages with “apt-get install package”, and then run “apt-get dist-upgrade”.

If you try that, then the DPKG::Post-Invoke rule will clean out /var/cache/apt/archives when you install the individual package(s). When you then run the dist-upgrade, apt-get will have to download all the packages again.

Better just to get into the habit of running apt-get clean or autoclean occasionally when you want to reclaim some disk space.