00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <sys/types.h>
00035 #include <signal.h>
00036 #include <time.h>
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
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
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);
00188 printf("SIGCHLD has been handled\n");
00189
00190 printf("\nRaising a SIGALRM signal\n");
00191 kill(getpid(), SIGALRM);
00192 printf("SIGALRM has been handled\n");
00193
00194 printf(gstr);
00195 }
00196
00200 void IgnoreSignal()
00201 {
00202 struct sigaction sa1,sa2;
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
00212 if (sigaction(SIGCHLD, &sa1, NULL) == -1)
00213 printf("sigaction for SIGCHLD failed\n");
00214
00215
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);
00221 printf("SIGCHLD was ignored\n");
00222
00223 printf("\nRaising a SIGALRM signal\n");
00224 kill(getpid(), SIGALRM);
00225 printf("SIGALRM was ignored\n");
00226
00227 printf(gstr);
00228 }
00229
00233 void MaskSignal()
00234 {
00235
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
00248 signal(SIGUSR1, SIGUSR1_handler);
00249 signal(SIGUSR2, SIGUSR2_handler);
00250
00251
00252 sigemptyset(&mask_set);
00253
00254 sigaddset(&mask_set, SIGUSR1);
00255
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;
00283 sigset_t waitset,outset;
00284 struct timespec timeout;
00285 siginfo_t info;
00286
00287 signal(SIGALRM, SIGALRM_handler);
00288 sigemptyset(&waitset);
00289 sigaddset(&waitset, SIGALRM);
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
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];
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
00360 signal(SIGPIPE, SIGPIPE_handler);
00361
00362
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
00373 close(fds[0]);
00374
00375
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
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
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;
00459 }