#define _FILE_OFFSET_BITS 64 #define _LARGEFILE_SOURCE 1 #define _LARGEFILE64_SOURCE 1 #include #include #include #include #include #include #include #define MAGIC 0x0badf00dL typedef int (*function_ptr)(void); struct { int fd; time_t last_pat; } watchdog; /* We don't like malloc */ void *xmalloc(size_t size) { return mmap((void *)0,size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,-1,0); } void xfree(void *mapping, size_t size) { munmap(mapping,size); } void init_dog(void) { watchdog.fd = 0; watchdog.last_pat = 0; } void open_dog(const char *device) { watchdog.fd = open(device,O_WRONLY); if(watchdog.fd == -1) { fprintf(stderr,"Error Opening Device\n"); exit(1); } } int pat_dog(void) { size_t ret = 0; ret = write(watchdog.fd,"\0",1); fsync(watchdog.fd); watchdog.last_pat = time(NULL); if(ret != 1) { return 1; } else { return 0; } } void sleep_remain(int seconds) { seconds -= time(NULL) - watchdog.last_pat; sleep(seconds); } int file_test(void) { char buffer[4096]; char filename[] = "/tmp/watchdog-file_test-XXXXXX"; int fd,i; size_t done = 0; fd = mkstemp(filename); if(fd != -1) { memset(buffer,0xff,4096); for(i = 0; done < 4096 && i < 10; ++i) { done += write(fd,buffer,4096); fsync(fd); } close(fd); unlink(filename); } if(done == 4096) { return 0; } else { return 1; } } int fork_test(void) { char filename[] = "/tmp/watchdog-fork_test-XXXXXX"; int fd; int ret_val = 1; int i; pid_t child = 0; long *map = NULL; /* Make a Temp File */ fd = mkstemp(filename); if(fd == -1) { return 1; } for(i = 0; i < sizeof(long); ++i) { write(fd,"\0",1); } fsync(fd); /* Map it */ map = mmap((void *)0, sizeof(long), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(map == NULL) { close(fd); unlink(filename); return 1; } /* Zero the Int */ (*map) = 0; msync(map,sizeof(long),MS_SYNC); /* Fork */ child = fork(); if(child == 0) { /* We are the Child */ (*map) = MAGIC; msync(map,sizeof(long),MS_INVALIDATE); exit(0); } else { wait(NULL); if((*map) == MAGIC) { ret_val = 0; } munmap(map, sizeof(long)); close(fd); unlink(filename); } return ret_val; } int malloc_test(void) { char *buffer = NULL; size_t page_size = getpagesize(); size_t size; for(size = 1; size < 32; ++size) { buffer = xmalloc(size*page_size); if(buffer == NULL) { return 1; } memset(buffer,0x00,size*page_size); xfree(buffer,size*page_size); } return 0; } void pat() { pat_dog(); sleep_remain(10); fprintf(stderr,"Pat() at %ld\n",time(NULL)); } const int num_tests = 3; function_ptr tests[3]; void set_tests(void) { tests[0] = &malloc_test; tests[1] = &file_test; tests[2] = &fork_test; } void set_signals(void) { signal(SIGHUP,SIG_IGN); //signal(SIGTERM,SIG_IGN); } int main(int argc, const char *argv[]) { int ret; int i; if(argc < 2) { fprintf(stderr, "Please specify a watchdog device\n"); exit(1); } set_tests(); set_signals(); init_dog(); open_dog(argv[1]); pat_dog(); for(;;) { for(i = 0; i < num_tests; ++i) { ret = tests[i](); if(ret == 0) { /* No More Tests for 60 Seconds */ for(ret = 0; ret < 6; ++ret) { pat(); } } } } return 0; }