Peeter Joot's (OLD) Blog.

Math, physics, perl, and programming obscurity.

Archive for December 18th, 2009

A fun regular expression for the day. change all function calls to another.

Posted by peeterjoot on December 18, 2009

Hit some nasty old school code today that dates back to our one-time 16-bit OS/2 port. I figured out that 730 lines of code for an ancient function called sqlepost() could all be removed if I could make a change of all lines like so:


(83 places). A desirable side effect of making this change is that we will stop logging the return code as a byte reversed hex number, and instead log it as a return code. Easier on developers and system testers alike.

perl -p is once again a good friend for this sort of task

\s*(.*?)\s*, # componentID -- unused.
\s*(.*?)\s*, # functionID
\s*(.*?)\s*, # probe
\s*(.*?)\s*, # index -- unused.
\s*(.*?)\s*, # size -- unused.
\s*&(.*?)\s*\)\s*; # rc
/pdLog( PD_DEV, $2, $6, $3, PD_LEVEL_SEV, 0 ) ;/x ;

I made a quick manual modification of each of the call sites that weren’t all in one line, with control-J in vim to put the whole function call on one line, then just had to run:

perl -p -i ./replacementScript `cat listOfFilesWithTheseCalls`

Voila! Very nice if I have to say so myself;)

EDIT: it was pointed out to me that the regular expressions used above are not entirely obvious.  Here’s a quick synopsis:

\s       space
.        any character
*        zero or more of the preceding
(.*)     capture an expression (creates $1, $2, ...)
            ie. zero or more of anything.
(.*?)    capture an expression, but don't be greedy, only capturing the
            minimal amount.
\(       a plain old start brace character (ie. non-capturing)
\)       a plain old end brace character.

Posted in C/C++ development and debugging., perl and general scripting hackery | Tagged: , , | Leave a Comment »

do not expect ‘kill -SEGV’ to kill.

Posted by peeterjoot on December 18, 2009

Occasionally our (DB2) testers or developers try to crash our code for test purposes with externally driven ‘kill -SEGV pid’. Once upon a time I also expected this to “work”, but this was because of not understanding how one drives core-file creation on Unix after handling the signal. Code that handles SIGSEGV (or other similar typically fatal signals) can re-install the default handler, SIG_DFL, to drive this core file creation. This is best illustrated with a bit of sample code

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

struct sigaction oldAction ;
char * null = 0 ;

extern "C"
void h( int sig )
   printf( "externally driven SEGV\n" ) ;

   // put things back to SIG_DFL, the old action, to drive core creation.
   sigaction( SIGSEGV, &oldAction, NULL ) ;

int main()
   struct sigaction a ;
   a.sa_flags = 0 ;
   sigemptyset( &a.sa_mask ) ;
   a.sa_handler = h ;

   sigaction( SIGSEGV, &a, &oldAction ) ;

   printf( "pre-sleep: pid: %u\n", (unsigned)getpid() ) ;

   sleep( 60 ) ;

   printf( "post-sleep... crashing for real\n" ) ;
   fflush( NULL ) ;

   memset( null, 0, 29472 ) ;

   printf( "post memset.  shouldn't get here\n" ) ;

   return 0 ;

If you execute this code, it will spit out the pid, and you can use that in a different window to drive a ‘kill -SEGV’. Here is output for such an attempt:

$ a.out
pre-sleep: pid: 5550
externally driven SEGV
post-sleep... crashing for real
Segmentation fault

The signal is caught by this trivial handler, a message printed, and it returns after putting the handler back (implicitly) to SIG_DFL. At that point a SIGSEGV will take us out, and the memset does so.

Note: This code sample is for illustration purposes, and is understood to be faulty in many ways. There is no rc checking for syscalls, the handler is not signal safe due to use of printf, sa_sigaction with SA_SIGINFO ought to be used to see if the signal was externally generated using the siginfo_t data (restoring SIG_DFL is not appropriate in that case), …

Posted in C/C++ development and debugging. | Tagged: , , | Leave a Comment »