Tuesday, March 27, 2007

signals (eg SIGTERM, SIGPIPE, SIGHUP, SIGINT)

First off, something a bit Off Topic. Why is it that all blog editors have to be so tiny. I have a maximized 1280x1024 window and the blog editor is about half of that. *sigh*

Anywho, todays topic: unix/linux signals. I had to introduce myself to them for a recent project at work where a wrote a threaded socket-ed server. I had used send and recv because they allowed for "MSG_NOSIGNAL" at least until I got home to my Mac OS X computer, which apparently doesn't have that flag (or if it does its not #defined the same way). At any rate its just as easy to handle the signal that is raised by a broken/disconnected socket, which is SIGPIPE (the broken pipe signal).

There are two (old) ways to handle such problems. The first way I learned was:
#include <sys/signal.h>

static void signalHandler() { //handle the signal somehow; }

int main()
{
// blah
signal(SIGPIPE,signalHandler);
//blah
}

This is a simple way to handle any signal and deal with it. The problem with this method is that if you are just ignoring the signal, you have to re register the signal handler every time it is used. One solution to the "only registered once" problem is to update our signal handler so it looks like this:

static void signalHandler()
{
//handle the signal somehow;
signal(SIGPIPE,signalHandler);
}

This is a good way to handle a reoccurring problem where you actually want to fix something and then handle it again. Obviously you don't have to do this for something you only want to handle once, such as say a SIGTERM, where you just want to close your sockets before exiting.

This is obviously much more than one might want to put in simply to ignore a signal however, which is why there is a function called:

sigignore(SIGPIPE);

This will ignore a signal to your program until the program quits.

I like this way of handling the SIGPIPE raised by a socket failure. Its not bad coding practice because sockets return either 0 or -1 on failure of a read/write, which is better anyway, because signal sending is only "supported" on a per application level. It might work and send it to the correct thread, but it is NOT guaranteed. Therefor you can only count on your main program to recieve the signals anyway. So by ignoring the signal (which would normally make your program take a crap) and checking the status of the socket on every send/recv (or read/write), your program has a good idea of what is going on.

Some common signals are:
Catchable:
SIGTERM = sent by kill among others
SIGPIPE = broken pipe, sent by dead sockets, pipes, etc.
SIGHUP = "hang up" sent by exiting the shell the process was running in etc.
SIGIO = configurable exception raised on sockets etc, when something is ready to happen (data recieved etc.)
SIGINT = "interrupt" sent by ctrl - c among other things.

Not able to be caught:
SIGKILL = sent by kill -9

There are more signals. Something like 22 I think, but those are the only ones I have run across so far, and I have only actually handled SIGTERM, SIGINT, and SIGPIPE. I like to handle SIGTERM and SIGINT so I can close my sockets before exiting
because it makes the program start quicker next time when it doesn't have to wait for previously bound sockets to time out before rebinding.

The last thing to note (sadly) is that this signal, sigignore, and all the other functions related in the man pages, are actually depricated. Thats not to say that they will be removed from any linux anytime soon. The new method is really overkill for anything I was doing, so I didn't bother to learn it. I hope that this method is never removed, because signal and sigignore are super easy ways to get things done. Im not disagreeing with "better" functionality, one of the features added in the new interface was ability to have a "previous" handler stored, which you could switch back to when you were done. Once again this is massive overkill for what I need to do, and in most cases, this will work just fine for years (I'm sure) to come.

Happy coding!

-Crusher4

Monday, March 26, 2007

Introduction

Well. This is my first "Tech Blog" post, so I suppose I'll give you some background about what this is all about.

As opposed to my other blogs which are about my "life" this blog I will try to keep on the topic of tech savvy things at the least, but at the moment my current focus are programs which can be compiled with gcc. That means my blog title should probably include Windows, but as of yet I've been to lazy to get mingw / mingcc working on my windows environment.

If you see any "tech bias" here it will probably be towards the mac/linux side...BUT, thats mostly because the shell environment in windows is pretty bleh compared to the alternatives. Don't get me wrong, I've taken plenty of windows IT classes.

Speaking of classes: I'm a Computer Science major at Washington State University. I came to WSU in 2002. I was here for a year and a half before I "left" due to academic deficiency (which means kicked out by the way). After a year and a half of Spokane Falls Community College aka SFCC (you are required to leave for a minimum of a year due to academic deficiency) I had quite a new outlook. Looking back on it, I'm glad I got the boot, because it allowed me to get an _ENTIRELY_ new perspective on a lot of things. For my first quarter at SFCC I took IS/IT classes which were quite enlightening and allowed me to learn a lot about windows in a domain environment. The real treat was when I started taking CS classes at SFCC. My teacher through my next 3 quarters of CS at SFCC was John Mill -- who is without a doubt the best computer science teacher I have ever had. I thought I knew quite a bit going in there, but anything that had hurt my brain to think about before SFCC like Binary Search Trees / Advanced Sorting and other topics, all really came together, which helped me to become a coder that likes to carefully consider his approaches before delving headlong into a project. I'm not saying I'm "uberfantastic", But I try to be the best I can. Anywho, going to SFCC really helped to cement the style of thinking that I needed to solve problems with code, without feeling overwhelmed. If there is any skill a coder needs, its not to be overwhelmed...you've just got to loop through the steps to solve the problem after all :)

So anyway. I'm currently in CS 360 422 and 317. To anyone who knows the WSU curriculum that means I'm in one real coding class and two pretty fluffy classes. 317 is my least favorite because its all about things like set theory, automata, etc. Things that make sense to me in practice, but not in theory. 422 is all about "coding in the real world" about testing, etc. Things that you'll have to deal with if you work at places like M$. Not something I look forward to, but not utterly impossible either, and its a pretty fun class anyway. 360 is my favorite class. It's called "operating systems" although its more like "low level coding in c in relation to linx and ext2fs". Anyway you slice it, its superfun, because every time you finish a lab for that class you feel accomplished. And I learn a lot of low level stuff that seems simple after the fact, but to learn on my own would be daunting.

I also have two "tech" jobs. One for student computing...which is basically an IT position, management, fixing, etc of computers -- however since I was just hired this semester, most of my job is sitting swiping people into labs and answering questions...but it still beats the hell out of the 4 years I worked at subway. ( I'm nearly 23 btw -- class of 2002 ). My other job has its IT elements, but is basically a "huge" graduate lab. I mean huge in the sense of how much coding they accomplish/research/etc. the actual "lab" is only about 16 computers. Its been really fun. I started out by re assembling the lab as best as I could. That having been mostly accomplished a couple weeks ago, my attentions turned to my first assignment, which happened to be writing a one way TCP proxy.

Using the knowledge of sockets I gained in 360 writing the initial code skeleton wasnt hard...but doing all the linux tricks that make a program "slick" has taken me days to learn. So over the course of the next few days I'll be discussing these low level linux signal / socket / thread / etc tricks and basic knowledge that I've learned.

So stay tuned :)

(sorry for the boring intro)

-Crusher4