00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <unistd.h>
00021 #include <sys/types.h>
00022 #include <signal.h>
00023 #include <time.h>
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
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
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);
00175 printf("SIGCHLD has been handled\n");
00176
00177 printf("\nRaising a SIGALRM signal\n");
00178 kill(getpid(), SIGALRM);
00179 printf("SIGALRM has been handled\n");
00180
00181 printf(gstr);
00182 }
00183
00187 void IgnoreSignal()
00188 {
00189 struct sigaction sa1,sa2;
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
00199 if (sigaction(SIGCHLD, &sa1, NULL) == -1)
00200 printf("sigaction for SIGCHLD failed\n");
00201
00202
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);
00208 printf("SIGCHLD was ignored\n");
00209
00210 printf("\nRaising a SIGALRM signal\n");
00211 kill(getpid(), SIGALRM);
00212 printf("SIGALRM was ignored\n");
00213
00214 printf(gstr);
00215 }
00216
00220 void MaskSignal()
00221 {
00222
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
00235 signal(SIGUSR1, SIGUSR1_handler);
00236 signal(SIGUSR2, SIGUSR2_handler);
00237
00238
00239 sigemptyset(&mask_set);
00240
00241 sigaddset(&mask_set, SIGUSR1);
00242
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;
00270 sigset_t waitset,outset;
00271 struct timespec timeout;
00272 siginfo_t info;
00273
00274 signal(SIGALRM, SIGALRM_handler);
00275 sigemptyset(&waitset);
00276 sigaddset(&waitset, SIGALRM);
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
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];
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
00347 signal(SIGPIPE, SIGPIPE_handler);
00348
00349
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
00360 close(fds[0]);
00361
00362
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
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
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;
00446 }