csci4061/notes/08-signals-code/non-reentrant.c~
Michael Zhang 041f660ccd
f
2018-01-29 17:28:37 -06:00

60 lines
1.8 KiB
C

// Shows dangers of using a non-reentrant function with signal
// handling. Strange things can happen due to the use of the
// non-reentrant function getpwnam() being called both in the main
// loop and signal handler. Uncommenting the getpwnam() in the signal
// handler causes unpredictable things to happen like a permanent
// stall of the program on Linux boxes.
//
// Adapted from Stevens and Rago Fig 10.5.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <string.h>
#define USERNAME "kauffman"
static void alarm_handler(int signo) {
printf("in signal handler\n");
struct passwd *rootptr = NULL;
// NON-REENTRANT FUNCTION CALL IN SIGNAL HANDLER
rootptr = getpwnam("root"); // fetch record associated with root password
if (rootptr == NULL){ // check for presence of root
printf("no root, that's weird...\n");
}
else{
printf("root looks okay\n");
}
alarm(1); // reset the alarm
printf("leaving signal handler\n");
}
int main(void) {
signal(SIGALRM, alarm_handler); // xhandle alarms in with the above function
alarm(1);
printf("Repeatedly checking on user '%s'\n",USERNAME);
while(1){
struct passwd *ptr = getpwnam(USERNAME); // non-reentrant call
if(ptr == NULL){
perror("couldn't find user");
exit(1);
}
if(strcmp(ptr->pw_name, USERNAME) != 0){ // should always be equal to USERNAME
printf("return value corrupted!, pw_name = %s\n",
ptr->pw_name);
exit(1);
}
// else{
// printf("%s looks okay\n",USERNAME); // verbose output
// }
}
exit(0);
}