Mike Chirico on 14 Feb 2004 23:35:03 -0000


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PLUG] Re: Interview Questions: System Admin (gabriel rosenkoetter)


> From: gabriel rosenkoetter <gr@eclipsed.net>
[snip]
> Ah, I didn't read the whole question. Do you mean the version of gcc
> used to compile the kernel? (This is, obviously, not information
> that's available under commercial Unix implementations, and I can't
> imagine why it would matter.)
>
> The portable way to answer the gcc part is just to ask gcc with
> --version, which is a syntax supported by most GNU tools.
>
I think it makes a difference if a program depends on real-time signals
being queued.
Here's a quick and dirty sample below.

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>


#define NUM_PROC 4
sig_atomic_t sigusr1_count = 0;


/* according to recent literature
this function call allows signals to
be pending, or queued provided real-time
signals are being used.  Currently, I have
2 versions of Linux

(works)
cat /proc/version
Linux version 2.4.20-28.9 (bhcompile@porky.devel.redhat.com) (gcc
version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #1 Thu Dec 18 13:45:22
EST 2003


(does not work)
2.4.20-28.8 #1 Thu Dec 18 12:53:39 EST 2003


*/


  /* handler may only execute once
for the first process only, the other
processes are dropped when they are
queued...so it's a race.  If the first
one finishes you're ok.  Unless the version of gcc compiled by
the kernel supports realtime signals for the user*/
void handler (int signal_number)
{
  ++sigusr1_count;
  fprintf(stderr,"in handler \n");
}

int main(void)
{
  struct sigaction sa;
  sigset_t blocked_sigs,no_sigs,all_sigs;
  pid_t p[NUM_PROC],pid;
  int i;

  sigfillset(&all_sigs);
  sigemptyset(&no_sigs);
  sigemptyset(&blocked_sigs);

  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = &handler;
  if( sigaction(SIGCHLD,&sa, NULL) == -1) {
    fprintf(stderr,"sigaction error \n");
    exit(-1);
  }

  for(i=0; i < NUM_PROC; ++i)
    {
      if ( (p[i] = fork()) == 0 ) {
	/* take out sleep and
	   put your main code here */
	sleep(2);
	exit(0);
      }
    }


  int status;
  while(sigusr1_count < NUM_PROC)
    {

      printf("before: sigsuspend %d\n",sigusr1_count);
      sigsuspend(&no_sigs);
      printf("after sigsuspend: %d \n",sigusr1_count);

      /* this is our circuit breaker for safety.
	 if the other processors finish at the same
	 time, they may not queue.  sigusr1_count will
	 never go above one!  You'll get a zombie
	 process...this protects us from that , should the Linux
  version not support realtime signals.  Only realtime
	 signals queue. Ref man 7 signal
      */
        for(i=0; i < NUM_PROC; ++i)
	  {
	    pid=waitpid(p[i],&status,0);
	    fprintf(stderr,"pid=%d\n",pid);
	    if ((sigusr1_count < NUM_PROC) && (i == (NUM_PROC -1))) {
	      fprintf(stderr,"Signal didn't queue\n");
	      exit(-2);
	    }
	  }

    }



  return 0;
}



Regards,

Mike Chirico

___________________________________________________________________________
Philadelphia Linux Users Group         --        http://www.phillylinux.org
Announcements - http://lists.phillylinux.org/mailman/listinfo/plug-announce
General Discussion  --   http://lists.phillylinux.org/mailman/listinfo/plug