examples/PIPS/posixsignals/basicSignals/basicSignals.c

00001 // basicSignals.c
00002 //
00003 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 // All rights reserved.
00005 // This component and the accompanying materials are made available
00006 // under the terms of "Eclipse Public License v1.0"
00007 // which accompanies this distribution, and is available
00008 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
00009 //
00010 // Initial Contributors:
00011 // Nokia Corporation - initial contribution.
00012 //
00013 // Contributors:
00014 //
00015 // Description:This example demonstrates the basic signal functionality .
00016 //
00017 
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <unistd.h>
00021 #include <sys/types.h>
00022 #include <signal.h>      //The header for signal functionality.
00023 #include <time.h>        //The header for timer functionality.
00024 #include <e32def.h>
00025 
00026 char const *gstr = "\nPress '7'+Enter to return to the options menu or 'e'+ENTER to exit the example\n";
00027 char const *gnote = "\nPress the Enter key to proceed with the use case\n";
00028 
00032 void PressKey()
00033         {
00034         fflush(stdout);
00035         getchar();
00036         }
00037 
00042 void timestamp(char *str) 
00043     {
00044     time_t t;
00045     time(&t);
00046     printf("The time %s is %s\n", str, ctime(&t));
00047     }
00048 
00053 void SIGCHLD_handler(int signum)
00054     {
00055     if(signum == SIGCHLD)
00056         printf("Now in SIGCHLD handler function\n");
00057     }
00058 
00063 void SIGALRM_handler(int signum)
00064     {
00065     if(signum == SIGALRM)
00066         printf("Now in SIGALRM handler function\n");
00067     }
00068 
00073 void SIGUSR1_handler(int signum)
00074     {
00075     if(signum == SIGUSR1)
00076         printf("Now in SIGUSR1 handler function\n");
00077     }
00078 
00083 void SIGUSR2_handler(int signum)
00084     {
00085     if(signum == SIGUSR2)
00086         printf("Now in SIGUSR2 handler function\n");
00087     
00088     sigrelse(SIGUSR1);
00089     printf("SIGUSR1 got released and hence its handler function will get called\n");
00090     }
00091 
00096 void SIGPIPE_handler(int signum)
00097     {
00098     if(signum == SIGPIPE)
00099         printf("In SIGPIPE handler function\n");
00100     }
00101 
00105 void DisplaySignalOptions()
00106     {
00107     printf("\nSignal options:\n");
00108     printf("1) Sending and handling a signal using the default handler\n");
00109     printf("2) Sending and handling a signal using a customized signal handler\n");
00110     printf("3) Ignoring an incoming signal\n");
00111     printf("4) Blocking and releasing a signal\n");
00112     printf("5) Waiting for a signal\n");
00113     printf("6) Generating and handling a SIGPIPE signal\n");
00114     printf("Type the number of the option you wish to run followed by an enter,\n");
00115     printf("or type 'e'+Enter to exit the example.\n");
00116     }
00117 
00121 void CallDefaultHandler()
00122     {
00123     pid_t my_pid;
00124     my_pid = getpid();
00125     printf("Raising a SIGCHLD signal\n");
00126     
00127     signal(SIGCHLD, SIG_DFL);
00128     
00129     //Raising SIGCHLD signal using kill command.
00130     kill(my_pid, SIGCHLD);
00131     
00132     printf("Default handler causes SIGCHLD to get ignored\n");
00133     PressKey();
00134     
00135     printf("\nRaising a SIGALRM signal\nDefault handler of SIGALRM will terminate the existing process.\n");
00136     printf("\nRestart the example to view the other use cases.\n");
00137     printf("Press the enter key to terminate the example.\n");
00138     PressKey();
00139     
00140     signal(SIGALRM, SIG_DFL);
00141     
00142     //Raising SIGALRM signal.
00143     kill(my_pid, SIGALRM);
00144     printf("After SIGALRM being raised\n");
00145     
00146     printf(gstr);
00147     }
00148 
00152 void CallSignalHandler()
00153     {
00154     struct sigaction sa1,sa2;
00155     sa1.sa_handler = SIGCHLD_handler;
00156     sigemptyset(&sa1.sa_mask);
00157     sa1.sa_flags = 0;  
00158     
00159     sa2.sa_handler = SIGALRM_handler;
00160     sigemptyset(&sa2.sa_mask);
00161     sa2.sa_flags = 0; 
00162     
00163     if (sigaction(SIGCHLD, &sa1, NULL) == -1)
00164         {
00165         printf("error in setting the handler for SIGCHLD\n");
00166         }
00167   
00168     if (sigaction(SIGALRM, &sa2, NULL) == -1)
00169         {
00170         printf("error in setting the handler for SIGALRM\n");
00171         }
00172     
00173     printf("\nRaising a SIGCHLD signal\n");
00174     kill(getpid(), SIGCHLD);                 //Raising SIGCHLD signal using kill command.
00175     printf("SIGCHLD has been handled\n");
00176     
00177     printf("\nRaising a SIGALRM signal\n");
00178     kill(getpid(), SIGALRM);                 //Raising SIGALRM signal using kill command.
00179     printf("SIGALRM has been handled\n");
00180     
00181     printf(gstr);
00182     }
00183 
00187 void IgnoreSignal()
00188     {
00189         struct sigaction sa1,sa2;   //The variables for holding signal specific settings, used in sigaction function call. 
00190         sa1.sa_handler = SIG_IGN;
00191         sigemptyset(&sa1.sa_mask);
00192         sa1.sa_flags = 0;  
00193         
00194         sa2.sa_handler = SIG_IGN;
00195         sigemptyset(&sa2.sa_mask);
00196         sa2.sa_flags = 0; 
00197         
00198         // Set the signal handler for SIGCHLD.
00199         if (sigaction(SIGCHLD, &sa1, NULL) == -1)
00200                    printf("sigaction for SIGCHLD failed\n");
00201         
00202         // Set the signal handler for SIGALRM.
00203         if (sigaction(SIGALRM, &sa2, NULL) == -1)
00204                 printf("sigaction for SIGALRM failed\n");
00205         
00206         printf("\nRaising a SIGCHLD signal\n");
00207         kill(getpid(), SIGCHLD);             //Raisisng SIGCHLD signal using kill command.
00208         printf("SIGCHLD was ignored\n");
00209         
00210         printf("\nRaising a SIGALRM signal\n");
00211         kill(getpid(), SIGALRM);             //Raisisng SIGALRM signal using kill command.
00212         printf("SIGALRM was ignored\n");
00213         
00214         printf(gstr);
00215     }
00216 
00220 void MaskSignal()
00221     {
00222     // Define a new mask set.
00223     sigset_t mask_set;
00224     
00225     printf("* This use case uses SIGUSR1 and SIGUSR2 signals to demonstrate the mask and the release of a signal\n");
00226     printf("* We mask the SIGUSR1 signal so that when it is raised it gets blocked and keeps pending until it is\nreleased.\n");
00227     printf("* We then raise the SIGUSR2 signal to release the blocked SIGUSR1 signal.\n");
00228     printf("* The custom handler of the SIGUSR2 signal releases SIGUSR1, and SIGUSR1's\ncustom handler gets called to handle it.\n");
00229     
00230     printf(gnote);
00231     PressKey();
00232     PressKey();
00233     
00234     // Set the signal handler for SIGUSR1 and SIGUSR2 signals.
00235     signal(SIGUSR1, SIGUSR1_handler);
00236     signal(SIGUSR2, SIGUSR2_handler);
00237    
00238     // Clearing the mask set so that it doesn't contain any signal numbers.
00239     sigemptyset(&mask_set);
00240     // Adding SIGUSR1 to the mask set.
00241     sigaddset(&mask_set, SIGUSR1);
00242     // Masking the signal.
00243     printf("Masking the SIGUSR1 signal\n");
00244     sigprocmask(SIG_SETMASK, &mask_set, NULL);
00245     
00246     printf("\nRaising the SIGUSR1 signal");
00247     printf(gnote);
00248     PressKey();
00249     
00250     raise(SIGUSR1);
00251     printf("SIGUSR1 was ignored as it was masked\n");
00252     
00253     printf("\nRaising the SIGUSR2 signal");
00254     printf(gnote);
00255     PressKey();
00256     
00257     raise(SIGUSR2);
00258     printf("SIGUSR2 has been handled\n");
00259     
00260     printf(gstr);
00261     }
00262 
00266 void WaitForSignal()
00267     {
00268     int count,result;
00269     const int delay = 2;                //Time delay of 2 seconds.
00270     sigset_t waitset,outset;            // Define new mask sets.
00271     struct timespec timeout;            // A variable for holding timeout values.
00272     siginfo_t info;                     // A variable for holding signal info.
00273     
00274     signal(SIGALRM, SIGALRM_handler);   // Set the signal handler for SIGALRM.
00275     sigemptyset(&waitset);
00276     sigaddset(&waitset, SIGALRM);       // Adding SIGALRM to mask set.
00277     sigprocmask(SIG_BLOCK, &waitset, NULL);   
00278      
00279     printf("* This use case demonstrates how a process waits for a SIGALRM signal.\n");
00280     printf("* A fixed timeout period of 5 seconds is set.\n");
00281     printf("* The SIGALRM signal is first blocked and then we wait on it until it is raised.\n");
00282     printf("* The SIGALRM signal is raised twice, once after 6 seconds and another after 4 seconds.\n");
00283     printf("* When SIGALRM is raised after 6 seconds an error is generated as timeout has occurred.\nBut when SIGALRM is raised after 4 seconds the signal is received.\n");
00284     printf("* Even though the SIGALRM signal is received it cannot be handled as it is blocked.\nHence we finally unblock it and handle it.\n");
00285     
00286     printf(gnote);
00287     PressKey();
00288     PressKey();
00289     
00290     //Setting the timeout for 5 seconds.
00291     timeout.tv_sec = 5;
00292     timeout.tv_nsec = 500;
00293     
00294     for(count=0;count<2;count++)
00295         {
00296         if(count)
00297             {
00298             printf("Raising SIGALRM after 6 sec\n");
00299             printf(gnote);
00300             PressKey();
00301             alarm(6);
00302             }
00303         else
00304             {
00305             printf("Raising SIGALRM after 4 sec\n");
00306             printf(gnote);
00307             PressKey();
00308             alarm(4);
00309             }    
00310         timestamp("before sigwait()");
00311         result = sigtimedwait(&waitset, &info, &timeout); 
00312       
00313         if( result == SIGALRM )
00314             printf("sigwait() returned successful for signal %d\n", info.si_signo);
00315         else 
00316             {
00317             printf("sigwait() returned an error, since the alarm was generated after the specified time period.error number = %d\n", errno);
00318             }
00319         timestamp("after sigwait()");
00320         sleep(delay);
00321         }
00322     
00323     printf("Press Enter to unblock the SIGALRM signal and handle it\n");
00324     PressKey();
00325     sigemptyset(&outset);
00326     sigprocmask(SIG_UNBLOCK, &waitset, &outset); 
00327     
00328     printf(gstr);
00329     }
00330 
00334 void HandleSigpipe()
00335     {
00336     int ret,fds[2];   // fds, used for holding the read and write descriptors for pipe
00337     printf("* This use case demonstrates how writing to a broken pipe generates a SIGPIPE signal.\n");
00338     printf("* We first create a pipe and obtain the read and write descriptors.\n");
00339     printf("* To obtain a broken pipe we close the read end of the pipe.\n");
00340     printf("* Once a write is performed to the broken pipe, an EPIPE error is returned\nand hence the SIGPIPE signal is generated.\n");
00341     
00342     printf(gnote);
00343     getchar();
00344     PressKey();
00345     
00346     //Set the signal handler for the SIGPIPE signal.
00347     signal(SIGPIPE, SIGPIPE_handler);
00348     
00349     //Create a pipe.
00350     ret = pipe(fds);
00351     if(ret != 0)
00352         {
00353         printf("Failed to create a pipe and the errno is %d\n",errno);
00354         }
00355     else
00356         {
00357         printf("The pipe was created successfully\n");
00358         }
00359     //Close the read end of a pipe.
00360     close(fds[0]); 
00361     
00362     //Write to a pipe whose read end is closed (a broken pipe).
00363     printf("Writing to a broken pipe\n");
00364     ret = write(fds[1], "sigpipe", 10);
00365     if((ret != -1) && (errno != EPIPE))
00366         {
00367         printf("Failed to generate the SIGPIPE signal on pipe\n");
00368         }
00369     else
00370         {
00371         printf("Writing to a pipe with the read end closed, has returned EPIPE and hence generated the SIGPIPE signal\n");
00372         }
00373     
00374     printf(gstr);
00375     }
00376 
00381 int main()
00382         {
00383         int character;
00384         int val = TRUE;
00385         //Welcome Note.
00386         printf("************************************************************************\n");
00387         printf("*                  Welcome to the Signal Example                       *\n");
00388         printf("*      This example demonstrates some basic signal use cases           *\n");
00389         printf("************************************************************************\n");
00390         printf("Please refer to the overview for a better understanding of this example.\n");
00391         
00392         //Generating menu for various signal functions.
00393         DisplaySignalOptions();
00394         while(val)  
00395             {
00396             while((character = getchar())!= '\n')
00397                 {                
00398                 switch(character)
00399                 {
00400                 case '1':
00401                      printf("\nDemonstrating sending and handling of 2 signals by the default handler\n");
00402                      printf("**********************************************************************\n");
00403                      CallDefaultHandler();
00404                      break;
00405                 case '2':
00406                      printf("\nDemonstrating sending and handling of 2 signals using a custom signal handler\n");
00407                      printf("*****************************************************************************\n");
00408                      CallSignalHandler();
00409                      break;
00410                 case '3':
00411                      printf("\nDemonstrating ignoring an incoming signal\n");
00412                      printf("*****************************************\n");
00413                      IgnoreSignal();
00414                      break;
00415                 case '4':
00416                      printf("\nDemonstrating masking and releasing of a signal\n");
00417                      printf("***********************************************\n");
00418                      MaskSignal();
00419                      break;
00420                 case '5':
00421                      printf("\nDemonstrating waiting for a signal\n");
00422                      printf("**********************************\n");
00423                      WaitForSignal();
00424                      break;
00425                 case '6':
00426                      printf("\nDemonstrating generating and handling a SIGPIPE signal\n");
00427                      printf("******************************************************\n");
00428                      HandleSigpipe();
00429                      break;
00430                 case '7':
00431                      DisplaySignalOptions();
00432                      break;
00433                 case 'e':
00434                     printf("Exiting from the main menu\n");
00435                     val = FALSE;
00436                     break;
00437                 default:
00438                     printf("You chose a wrong option!!! Select again.\n");
00439                     break;
00440                 }
00441                 }          
00442             }    
00443         printf("Ok [Press the Enter key to exit]\n");
00444         PressKey();
00445         return EXIT_SUCCESS;    //Returns the success code.
00446         }

Generated by  doxygen 1.6.2