Canonical Voices

Posts tagged with 'c'

Colin Ian King

Using PR_SET_PDEATHSIG to reap child processes

The prctl() system call provides a rather useful PR_SET_PDEATHSIG option to allow a signal to be sent to child processes when the parent unexpectedly dies. A quick and dirty mechanism is trigger the SIGHUP or SIGKILL signal to kill the child immediately, or perhaps more elegantly to invoke a resource tidy up before exiting.

In the trivial example below, we use the SIGUSR1 signal to inform the child that the parent has died. I know printf() should not be used in a signal handler, it just makes the example simpler.

 #include <stdlib.h>                                 
#include <unistd.h>
#include <signal.h>
#include <sys/prctl.h>
#include <err.h>

void sigusr1_handler(int dummy)
printf("Parent died, child now exiting\n");

int main()
pid_t pid;

pid = fork();
if (pid < 0)
err(1, "fork failed");
if (pid == 0) {
/* Child */
if (signal(SIGUSR1, sigusr1_handler) == SIG_ERR)
err(1, "signal failed");
if (prctl(PR_SET_PDEATHSIG, SIGUSR1) < 0)
err(1, "prctl failed");

for (;;)
if (pid > 0) {
/* Parent */
printf("Parent exiting...\n");

return 0;

..the child process sits in an infinite loop, performing 60 second sleeps.  The parent sleeps for 5 seconds and then exits.  The child is then sent a SIGUSR1 signal and the handler exits.  In practice the signal handler would be used to trigger a more sophisticated clean up of resources if required.

Anyhow, this is a useful Linux feature that seems to be overlooked.

Read more
Colin Ian King

Smackerel of Opinion

It is approaching the Christmas Holiday season, so it's that time again to write some slightly obfuscated C in a seasonal way.  This year I thought I would try some coloured ASCII art for the output for a little variety.

#define r(s) s[e%(sizeof s-1)]
#include /* */
#define S "%s"/* Have */
#define u printf(/* a */
#define c )J/* Merry */
#define W "H"/* Christmas */
#define e rand()/* and */
#define U(i) v[i]/* a */
#define C(q) q[]=/* Happy */
#define J ;;/* New Year */
#define O [v]/* Colin.I.King */

typedef a
; a m, v[6] ,
H;a main(
){char C(
"*Oo", C(t
)"^~#",Q[ ]=
)".x+*";u S"2"
"m",o,o, o
c while(U(!!m)
<22)u S"%dm%39s\n" ,
o,0 O++>19?42:',',""
c while(0 O++<'~') u S
%39,o,r(s)c for(J){1 O=1
-U(1),srand(v),u S"0;0"W S
"0;2;%dm",o,o,' 'c for(m=0
;m>>4<1;++m){u S"%d;%d"W,o
, m+2,20-m c;for(H=0;H<1+(m
<<1);H++){4 O=!H|H==m<<1 ,
2 O=!(e&05),U(3)=H>m*5/
3,5 O=r(D)J if(4 O|U(
2)){u S"%d;%d;3%cm"
:'*',3 O?2:1+(U(1)^(1&e;)),r(Q),U(5)c}else u S"42;32\
;%dm%c",o,1+3 O,r(t)c u S"0m",o c} }while(m<19)u S"\
%d;19"W S"33;2;7m #\n",o,1+ ++m,o c sleep(m>=-H c}}

The source can be downloaded from here and compiled and run as follows:

gcc snowman.c -o snowman

and press control-C to exit when you have seen enough.

Read more
Colin Ian King

Finding small bugs

Over the past few months I've been using static code analysis tools such as cppcheck, Coverity Scan and also smatch on various open source projects.   I've generally found that most open source code is fairly well written, however, most suffer a common pattern of bugs on the error handling paths.  Typically, these are not free'ing up memory or freeing up memory incorrectly.  Other frequent bugs are not initialising variables and overly complex code paths that introduce subtle bugs when certain rare conditions are occur.  Most of these bugs are small and very rarely hit; some of these just silently do things wrong while others can potentially trigger segmentation faults.

The --force option in cppcheck to force the checking of every build configuration has been very useful in finding code paths that are rarely built, executed or tested and hence are likely to contain bugs.

I'm coming to the conclusion that whenever I have to look at some new code I should take 5 minutes or so throwing it at various static code analysis tools to see what pops out and being a good citizen and fixing these and sending these upstream. It's not too much effort and helps reduce some of those more obscure bugs that rarely bite but do linger around in code.

Read more
Colin Ian King

Infinite Snowflake

So it's close to the Christmas Holiday season, so I thought I would spend some time writing something seasonal.   My son, who is rather mathematically minded, was asking me about finding reoccurring digits in reciprocals of primes, for example 1/7, 1/11, 1/13 etc., and somehow this got me looking at the binary digits of Pi, and after a little more browsing around wikipedia onto the Thue-Morse binary sequence.

The Thue-Morse binary sequence starts with zero and one successively appends to the existing sequence the boolean compliment of the sequence so far.   One interesting feature is that a turtle graphics program can be written to control the turtle by feeding it the successive digits from the sequence so that:

  • A zero moves the cursor forward by a step
  • A one turns the cursor anti-clockwise by 60 degress (or pi/3 radians)
 ..and a Koch snowflake is drawn.  So, I've implemented this in C and obfuscated it a little just for fun:

#include <math.h>
#define Q (1<<9)
#define M /**/for
#define E(b,a) {\
J q=1^(X+b)[3+Q*\
int /*/*/ typedef
#define W double
#define z (Q<<5)

J;J X[3+(Q *Q)]
,t[z ] ;J main(
){ W o= Q >>1,V=
o/5, a=0; M (1 [X
]=1; X[1] <z;X
[1 ] *=2) for(
X[2] =0;X [2]<
X[1] ;X[2 ]++,
t[X[ 2]+X [1]]
=1^t [X[2 ]]);
for( 0[X] =0;X
[0]< 3;0[ X]++
)for (X[2] =0;X
[2]< z;X[ 2]++
)if( t[X[ 2]])
a-=( M_PI /3.0
);else{o+= cos(a ); V+=

sin(a);X[3+( int)o+Q*(int)V]|=1;}printf(
"P6 %d %d 1 ",Q,Q);M(1[X] =0;X[1]<Q;X[1]
++)M(2[X]=0;X[ 2]<Q;X[2]++)E(2[X],X[1]);
return 0;} /* Colin Ian King 2013 */

To build and run:
gcc koch-binary.c -lm -o koch-binary 
./koch-binary | ppmtojpeg > koch-binary.jpg
And the result is a koch-snowflake:

The original source code can be found here. It contains a 512 x 512 turtle graphics plotter, a Thue-Morse binary sequence generator and a PPM output backend. Anyway, have fun figuring out how it works (it is only mildly obfuscated) and have a great Christmas!

Read more
Colin Ian King

open() using O_WRONLY | O_RDWR

One of the lesser known Linux features is that one can open a file with the flags O_WRONLY | O_RDWR.   One requires read and write permission to perform the open(), however, the flags indicate that no reading or writing is to be done on the file descriptor.   It is useful for operations such as ioctl() where we also want to ensure we don't actually do any reading or writing to a device.  A bunch of utilities such as LILO seem to use this obscure feature. 

LILO defines these flags as O_NOACCESS as follows:

 #ifdef O_ACCMODE  
 /* open a file for "no access" */  
 # define O_NOACCESS 3  
 #endif in this example, you may find these flags more widely known as O_NOACCESS even though they are not defined in the standard fcntl.h headers.

Below is a very simple example of the use of O_WRONLY | O_RDWR:

 #include <stdio.h>  
 #include <stdlib.h>  
 #include <unistd.h>  
 #include <sys/ioctl.h>  
 #include <fcntl.h>  
 int main(int argc, char **argv)  
      int fd;  
      struct winsize ws;  
      if ((fd = open("/dev/tty", O_WRONLY | O_RDWR)) < 0) {  
           perror("open /dev/tty failed");  
      if (ioctl(fd, TIOCGWINSZ, &ws) == 0)  
           printf("%d x %d\n", ws.ws_row, ws.ws_col);  

It is a little arcane and not portable but also an interesting feature to know about.

Read more