// File: hwwatchdog.cpp // Purpose: Simulate a HW-Watchdog, which kills given processes after a given interval, // if it was not triggered on a named semaphore. see usage text. // Authors: Pierre Schnarz, Sven Eisenhauer // 14.06.2010 Initial coding // // Note: Named Semaphore code is POSIX. Tested on Linux only, show work on QNX. // Perhaps check header files on QNX // Important: in killProcs change cmd to list processes! // #ifdef LINUX #include #include #include #include #include #include #include #include #include #include // ugly global variables. needed in sig_handler char* semName; sem_t* semPtr; void usage(const char* progname) { printf("Usage: %s \n",progname); printf("\ttimeout:\tseconds to wait until watchdog time out\n"); printf("\tsemaphore_name:\tname of the semaphore to trigger watchdog\n"); printf("\t\t\tfull path will become /dev/shm/sem.\n"); printf("\tproc_name: fname (executable name) of processes to kill\n"); printf("Exit with Crtl-C\n"); } void sigint_handler(int sig) { printf("exiting\n"); sem_close(semPtr); sem_unlink(semName); exit(EXIT_SUCCESS); } void killProcs(char* procName) { FILE* fp; const int BUFF_SIZE = 4096; //TODO: make cmd portable to QNX (pidin something...) const char* cmd = "ps -eo pid,fname"; char buffer[BUFF_SIZE]; fp = popen(cmd,"r"); int pid = -1; int byte_count = 0; char res; int kill_res = -1; while (((res = fgetc(fp)) != EOF) && (byte_count < BUFF_SIZE) ) { buffer[byte_count++] = res; } char* line = strtok(buffer,"\n"); //int line_count = 0; while( (line=strtok(NULL,"\n")) != NULL ) { char fname[8]; sscanf(line,"%d %s",&pid,fname); //printf("line %d: [%s] pid: %d fname: [%s]\n",++line_count,line,pid,fname); if(strncmp(procName,fname,8) == 0) { printf("killing process %s pid:%d\n",fname,pid); kill_res = kill(pid,SIGTERM); if(kill_res != 0) { printf("Error killing %d : %d\n",pid,errno); } else { printf("Killed %d\n",pid); } } } pclose(fp); } int main(int argc, char** argv) { struct timespec ts; mode_t semMode = S_IRWXU|S_IRWXG|S_IRWXO; int s; long timeOut; const char* progName = argv[0]; char* proc; if(argc != 4) { usage(progName); exit(EXIT_FAILURE); } timeOut = strtol(argv[1],NULL,10); semName = argv[2]; proc = argv[3]; if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { printf("clock_gettime failed\n"); exit(EXIT_FAILURE); } // set signal handler for cleanup (void) signal(SIGINT,sigint_handler); ts.tv_sec += timeOut; // wait timeOut seconds semPtr = sem_open(semName,O_CREAT,semMode,0); if(SEM_FAILED == semPtr) { printf("Could not create named semaphore\n"); return -1; } do { // wait until time specified in ts on semaphore s = sem_timedwait(semPtr, &ts); /* Check what happened */ if (s == -1) { if (errno == ETIMEDOUT) { printf("sem_timedwait() timed out\n"); printf("kill Proccesses\n"); killProcs(proc); } else { printf("sem_timedwait some other error: %d\n",errno); exit(EXIT_FAILURE); } } else { printf("sem_timedwait() succeeded. Watchdog triggered\n"); } if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { printf("clock_gettime failed\n"); return -1; } ts.tv_sec += timeOut; // wait timeOut seconds printf("next loop hw watchdog\n"); } while (true); exit(EXIT_SUCCESS); } #endif // LINUX