Linux Programming

Profiling Input/Output performance

There are various nice tools for program profiling when it comes to CPU usage like gprof or oprofile. Those tools will tell you exactly which functions in your code consume most CPU time, where they are called, how often etc. But what if your program is slower than it should be because it waits for I/O disk operations? How can you check if the I/O is the bottleneck and what are the slowest operations?

Not so obvious multi-thread programming specific bugs.

We all know that when writing multi-threaded programs one should remember about few more details like locking, using thread-safe libraries etc. Here is a list of not-so obvious bugs specific to multi-threaded programs. Many of them are not mentioned in documentation or tutorials for beginners, but I think everybody who is using threads will hit them eventually.

Threads and fork(): think twice before mixing them.

When debugging a program I came across a bug that was caused by using fork(2) in a multi-threaded program. I thought it's worth to write some words about mixing POSIX threads with fork(2) because there are non-obvious problems when doing that.

All about Linux signals

In most cases if you want to handle a signal in your application you write a simple signal handler like:

void handler (int sig)

and use the signal(2) system function to run it when a signal is delivered to the process. This is the simplest case, but signals are more interesting than that! Information contained in this article is useful for example when you are writing a daemon and must handle interrupting your program properly without interrupting the current operation or the whole program.

Waiting for a signal with timeout using sigtimedwait()

/* The program creates a child process and waits for it to finish. If a timeout
 * elapses the child is killed. Waiting is done using sigtimedwait().

Blocking signals with sigprocmask()

/** This program blocks SIGTERM signal for 10 seconds using sigprocmask(2)
 * After that the signal is unblocked and the queued signal is handled.
 */
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
 
static int got_signal = 0;
 
static void hdl (int sig)
{
	got_signal = 1;
}
 
int main (int argc, char *argv[])
{
	sigset_t mask;
	sigset_t orig_mask;
	struct sigaction act;
 
	memset (&act, 0, sizeof(act));
	act.sa_handler = hdl;
 
	if (sigaction(SIGTERM, &act, 0)) {
		perror ("sigaction");
		return 1;
	}
 
	sigemptyset (&mask);
	sigaddset (

Handling interruption of system calls by signals

/** Example of handling cases when system calls are interrupted by
 * a signal. This program copies its standard input to the standard output.
 * Here read() and write() may be interrupted.

Example of using signalfd()

/* Example of use of a Linux-specific call - signalfd() to handle signals using
 * a file descriptor.
 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/signalfd.h>
#include <string.h>
 
int main (int argc, char *argv[])
{
	int sfd;
	sigset_t mask;
 
	/* We will handle SIGTERM and SIGINT. */
	sigemptyset (&mask);
	sigaddset (&mask, SIGTERM);
	sigaddset (&mask, SIGINT);
 
	/* Block the signals thet we handle using signalfd(), so they don't
	 * cause signal handlers or default signal actions to execute.

Example of using sigaction()

/* Example of using sigaction() to setup a signal handler with 3 arguments
 * including siginfo_t.
 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
 
static void hdl (int sig, siginfo_t *siginfo, void *context)
{
	printf ("Sending PID: %ld, UID: %ld\n",
			(long)siginfo->si_pid, (long)siginfo->si_uid);
}
 
int main (int argc, char *argv[])
{
	struct sigaction act;
 
	memset (&act, '\0', sizeof(act));
 
	/* Use the sa_sigaction field because the handles has two additional parameters */
	act.sa_sigaction = &hdl;
 
	/* The SA_SIGINFO flag tells 

SIGBUS handling

/* Example of SIGBUS handling. A read from mmap()ed memory is invalid because
 * a file was shrinked. SIGBUS is sent to the process, but we handle it and
 * jump to another place in the program so it doesn't crash.
 *
 * Run this program with or without the 'shrink' argument.
 */
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <setjmp.h>
 
/* Size of the file in pages.
Syndicate content