examples/PIPS/posixsignals/basicSignals/basicSignals.c

00001 /*
00002 Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description: This example demonstrates the basic signal functionality.
00028 */
00029 
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <sys/types.h>
00035 #include <signal.h>      //The header for signal functionality.
00036 #include <time.h>        //The header for timer functionality.
00037 #include <e32def.h>
00038 
00039 char const *gstr = "\nPress '7'+Enter to return to the options menu or 'e'+ENTER to exit the example\n";
00040 char const *gnote = "\nPress the Enter key to proceed with the use case\n";
00041 
00045 void PressKey()
00046         {
00047         fflush(stdout);
00048         getchar();
00049         }
00050 
00055 void timestamp(char *str) 
00056     {
00057     time_t t;
00058     time(&t);
00059     printf("The time %s is %s\n", str, ctime(&t));
00060     }
00061 
00066 void SIGCHLD_handler(int signum)
00067     {
00068     if(signum == SIGCHLD)
00069         printf("Now in SIGCHLD handler function\n");
00070     }
00071 
00076 void SIGALRM_handler(int signum)
00077     {
00078     if(signum == SIGALRM)
00079         printf("Now in SIGALRM handler function\n");
00080     }
00081 
00086 void SIGUSR1_handler(int signum)
00087     {
00088     if(signum == SIGUSR1)
00089         printf("Now in SIGUSR1 handler function\n");
00090     }
00091 
00096 void SIGUSR2_handler(int signum)
00097     {
00098     if(signum == SIGUSR2)
00099         printf("Now in SIGUSR2 handler function\n");
00100     
00101     sigrelse(SIGUSR1);
00102     printf("SIGUSR1 got released and hence its handler function will get called\n");
00103     }
00104 
00109 void SIGPIPE_handler(int signum)
00110     {
00111     if(signum == SIGPIPE)
00112         printf("In SIGPIPE handler function\n");
00113     }
00114 
00118 void DisplaySignalOptions()
00119     {
00120     printf("\nSignal options:\n");
00121     printf("1) Sending and handling a signal using the default handler\n");
00122     printf("2) Sending and handling a signal using a customized signal handler\n");
00123     printf("3) Ignoring an incoming signal\n");
00124     printf("4) Blocking and releasing a signal\n");
00125     printf("5) Waiting for a signal\n");
00126     printf("6) Generating and handling a SIGPIPE signal\n");
00127     printf("Type the number of the option you wish to run followed by an enter,\n");
00128     printf("or type 'e'+Enter to exit the example.\n");
00129     }
00130 
00134 void CallDefaultHandler()
00135     {
00136     pid_t my_pid;
00137     my_pid = getpid();
00138     printf("Raising a SIGCHLD signal\n");
00139     
00140     signal(SIGCHLD, SIG_DFL);
00141     
00142     //Raising SIGCHLD signal using kill command.
00143     kill(my_pid, SIGCHLD);
00144     
00145     printf("Default handler causes SIGCHLD to get ignored\n");
00146     PressKey();
00147     
00148     printf("\nRaising a SIGALRM signal\nDefault handler of SIGALRM will terminate the existing process.\n");
00149     printf("\nRestart the example to view the other use cases.\n");
00150     printf("Press the enter key to terminate the example.\n");
00151     PressKey();
00152     
00153     signal(SIGALRM, SIG_DFL);
00154     
00155     //Raising SIGALRM signal.
00156     kill(my_pid, SIGALRM);
00157     printf("After SIGALRM being raised\n");
00158     
00159     printf(gstr);
00160     }
00161 
00165 void CallSignalHandler()
00166     {
00167     struct sigaction sa1,sa2;
00168     sa1.sa_handler = SIGCHLD_handler;
00169     sigemptyset(&sa1.sa_mask);
00170     sa1.sa_flags = 0;  
00171     
00172     sa2.sa_handler = SIGALRM_handler;
00173     sigemptyset(&sa2.sa_mask);
00174     sa2.sa_flags = 0; 
00175     
00176     if (sigaction(SIGCHLD, &sa1, NULL) == -1)
00177         {
00178         printf("error in setting the handler for SIGCHLD\n");
00179         }
00180   
00181     if (sigaction(SIGALRM, &sa2, NULL) == -1)
00182         {
00183         printf("error in setting the handler for SIGALRM\n");
00184         }
00185     
00186     printf("\nRaising a SIGCHLD signal\n");
00187     kill(getpid(), SIGCHLD);                 //Raising SIGCHLD signal using kill command.
00188     printf("SIGCHLD has been handled\n");
00189     
00190     printf("\nRaising a SIGALRM signal\n");
00191     kill(getpid(), SIGALRM);                 //Raising SIGALRM signal using kill command.
00192     printf("SIGALRM has been handled\n");
00193     
00194     printf(gstr);
00195     }
00196 
00200 void IgnoreSignal()
00201     {
00202         struct sigaction sa1,sa2;   //The variables for holding signal specific settings, used in sigaction function call. 
00203         sa1.sa_handler = SIG_IGN;
00204         sigemptyset(&sa1.sa_mask);
00205         sa1.sa_flags = 0;  
00206         
00207         sa2.sa_handler = SIG_IGN;
00208         sigemptyset(&sa2.sa_mask);
00209         sa2.sa_flags = 0; 
00210         
00211         // Set the signal handler for SIGCHLD.
00212         if (sigaction(SIGCHLD, &sa1, NULL) == -1)
00213                    printf("sigaction for SIGCHLD failed\n");
00214         
00215         // Set the signal handler for SIGALRM.
00216         if (sigaction(SIGALRM, &sa2, NULL) == -1)
00217                 printf("sigaction for SIGALRM failed\n");
00218         
00219         printf("\nRaising a SIGCHLD signal\n");
00220         kill(getpid(), SIGCHLD);             //Raisisng SIGCHLD signal using kill command.
00221         printf("SIGCHLD was ignored\n");
00222         
00223         printf("\nRaising a SIGALRM signal\n");
00224         kill(getpid(), SIGALRM);             //Raisisng SIGALRM signal using kill command.
00225         printf("SIGALRM was ignored\n");
00226         
00227         printf(gstr);
00228     }
00229 
00233 void MaskSignal()
00234     {
00235     // Define a new mask set.
00236     sigset_t mask_set;
00237     
00238     printf("* This use case uses SIGUSR1 and SIGUSR2 signals to demonstrate the mask and the release of a signal\n");
00239     printf("* We mask the SIGUSR1 signal so that when it is raised it gets blocked and keeps pending until it is\nreleased.\n");
00240     printf("* We then raise the SIGUSR2 signal to release the blocked SIGUSR1 signal.\n");
00241     printf("* The custom handler of the SIGUSR2 signal releases SIGUSR1, and SIGUSR1's\ncustom handler gets called to handle it.\n");
00242     
00243     printf(gnote);
00244     PressKey();
00245     PressKey();
00246     
00247     // Set the signal handler for SIGUSR1 and SIGUSR2 signals.
00248     signal(SIGUSR1, SIGUSR1_handler);
00249     signal(SIGUSR2, SIGUSR2_handler);
00250    
00251     // Clearing the mask set so that it doesn't contain any signal numbers.
00252     sigemptyset(&mask_set);
00253     // Adding SIGUSR1 to the mask set.
00254     sigaddset(&mask_set, SIGUSR1);
00255     // Masking the signal.
00256     printf("Masking the SIGUSR1 signal\n");
00257     sigprocmask(SIG_SETMASK, &mask_set, NULL);
00258     
00259     printf("\nRaising the SIGUSR1 signal");
00260     printf(gnote);
00261     PressKey();
00262     
00263     raise(SIGUSR1);
00264     printf("SIGUSR1 was ignored as it was masked\n");
00265     
00266     printf("\nRaising the SIGUSR2 signal");
00267     printf(gnote);
00268     PressKey();
00269     
00270     raise(SIGUSR2);
00271     printf("SIGUSR2 has been handled\n");
00272     
00273     printf(gstr);
00274     }
00275 
00279 void WaitForSignal()
00280     {
00281     int count,result;
00282     const int delay = 2;                //Time delay of 2 seconds.
00283     sigset_t waitset,outset;            // Define new mask sets.
00284     struct timespec timeout;            // A variable for holding timeout values.
00285     siginfo_t info;                     // A variable for holding signal info.
00286     
00287     signal(SIGALRM, SIGALRM_handler);   // Set the signal handler for SIGALRM.
00288     sigemptyset(&waitset);
00289     sigaddset(&waitset, SIGALRM);       // Adding SIGALRM to mask set.
00290     sigprocmask(SIG_BLOCK, &waitset, NULL);   
00291      
00292     printf("* This use case demonstrates how a process waits for a SIGALRM signal.\n");
00293     printf("* A fixed timeout period of 5 seconds is set.\n");
00294     printf("* The SIGALRM signal is first blocked and then we wait on it until it is raised.\n");
00295     printf("* The SIGALRM signal is raised twice, once after 6 seconds and another after 4 seconds.\n");
00296     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");
00297     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");
00298     
00299     printf(gnote);
00300     PressKey();
00301     PressKey();
00302     
00303     //Setting the timeout for 5 seconds.
00304     timeout.tv_sec = 5;
00305     timeout.tv_nsec = 500;
00306     
00307     for(count=0;count<2;count++)
00308         {
00309         if(count)
00310             {
00311             printf("Raising SIGALRM after 6 sec\n");
00312             printf(gnote);
00313             PressKey();
00314             alarm(6);
00315             }
00316         else
00317             {
00318             printf("Raising SIGALRM after 4 sec\n");
00319             printf(gnote);
00320             PressKey();
00321             alarm(4);
00322             }    
00323         timestamp("before sigwait()");
00324         result = sigtimedwait(&waitset, &info, &timeout); 
00325       
00326         if( result == SIGALRM )
00327             printf("sigwait() returned successful for signal %d\n", info.si_signo);
00328         else 
00329             {
00330             printf("sigwait() returned an error, since the alarm was generated after the specified time period.error number = %d\n", errno);
00331             }
00332         timestamp("after sigwait()");
00333         sleep(delay);
00334         }
00335     
00336     printf("Press Enter to unblock the SIGALRM signal and handle it\n");
00337     PressKey();
00338     sigemptyset(&outset);
00339     sigprocmask(SIG_UNBLOCK, &waitset, &outset); 
00340     
00341     printf(gstr);
00342     }
00343 
00347 void HandleSigpipe()
00348     {
00349     int ret,fds[2];   // fds, used for holding the read and write descriptors for pipe
00350     printf("* This use case demonstrates how writing to a broken pipe generates a SIGPIPE signal.\n");
00351     printf("* We first create a pipe and obtain the read and write descriptors.\n");
00352     printf("* To obtain a broken pipe we close the read end of the pipe.\n");
00353     printf("* Once a write is performed to the broken pipe, an EPIPE error is returned\nand hence the SIGPIPE signal is generated.\n");
00354     
00355     printf(gnote);
00356     getchar();
00357     PressKey();
00358     
00359     //Set the signal handler for the SIGPIPE signal.
00360     signal(SIGPIPE, SIGPIPE_handler);
00361     
00362     //Create a pipe.
00363     ret = pipe(fds);
00364     if(ret != 0)
00365         {
00366         printf("Failed to create a pipe and the errno is %d\n",errno);
00367         }
00368     else
00369         {
00370         printf("The pipe was created successfully\n");
00371         }
00372     //Close the read end of a pipe.
00373     close(fds[0]); 
00374     
00375     //Write to a pipe whose read end is closed (a broken pipe).
00376     printf("Writing to a broken pipe\n");
00377     ret = write(fds[1], "sigpipe", 10);
00378     if((ret != -1) && (errno != EPIPE))
00379         {
00380         printf("Failed to generate the SIGPIPE signal on pipe\n");
00381         }
00382     else
00383         {
00384         printf("Writing to a pipe with the read end closed, has returned EPIPE and hence generated the SIGPIPE signal\n");
00385         }
00386     
00387     printf(gstr);
00388     }
00389 
00394 int main()
00395         {
00396         int character;
00397         int val = TRUE;
00398         //Welcome Note.
00399         printf("************************************************************************\n");
00400         printf("*                  Welcome to the Signal Example                       *\n");
00401         printf("*      This example demonstrates some basic signal use cases           *\n");
00402         printf("************************************************************************\n");
00403         printf("Please refer to the overview for a better understanding of this example.\n");
00404         
00405         //Generating menu for various signal functions.
00406         DisplaySignalOptions();
00407         while(val)  
00408             {
00409             while((character = getchar())!= '\n')
00410                 {                
00411                 switch(character)
00412                 {
00413                 case '1':
00414                      printf("\nDemonstrating sending and handling of 2 signals by the default handler\n");
00415                      printf("**********************************************************************\n");
00416                      CallDefaultHandler();
00417                      break;
00418                 case '2':
00419                      printf("\nDemonstrating sending and handling of 2 signals using a custom signal handler\n");
00420                      printf("*****************************************************************************\n");
00421                      CallSignalHandler();
00422                      break;
00423                 case '3':
00424                      printf("\nDemonstrating ignoring an incoming signal\n");
00425                      printf("*****************************************\n");
00426                      IgnoreSignal();
00427                      break;
00428                 case '4':
00429                      printf("\nDemonstrating masking and releasing of a signal\n");
00430                      printf("***********************************************\n");
00431                      MaskSignal();
00432                      break;
00433                 case '5':
00434                      printf("\nDemonstrating waiting for a signal\n");
00435                      printf("**********************************\n");
00436                      WaitForSignal();
00437                      break;
00438                 case '6':
00439                      printf("\nDemonstrating generating and handling a SIGPIPE signal\n");
00440                      printf("******************************************************\n");
00441                      HandleSigpipe();
00442                      break;
00443                 case '7':
00444                      DisplaySignalOptions();
00445                      break;
00446                 case 'e':
00447                     printf("Exiting from the main menu\n");
00448                     val = FALSE;
00449                     break;
00450                 default:
00451                     printf("You chose a wrong option!!! Select again.\n");
00452                     break;
00453                 }
00454                 }          
00455             }    
00456         printf("Ok [Press the Enter key to exit]\n");
00457         PressKey();
00458         return EXIT_SUCCESS;    //Returns the success code.
00459         }

Generated by  doxygen 1.6.2