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 }
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.