leapcrash.c (2291B)
1/* Demo leapsecond deadlock 2 * by: John Stultz (john.stultz@linaro.org) 3 * (C) Copyright IBM 2012 4 * (C) Copyright 2013, 2015 Linaro Limited 5 * Licensed under the GPL 6 * 7 * This test demonstrates leapsecond deadlock that is possible 8 * on kernels from 2.6.26 to 3.3. 9 * 10 * WARNING: THIS WILL LIKELY HARD HANG SYSTEMS AND MAY LOSE DATA 11 * RUN AT YOUR OWN RISK! 12 * To build: 13 * $ gcc leapcrash.c -o leapcrash -lrt 14 */ 15 16 17 18#include <stdio.h> 19#include <stdlib.h> 20#include <time.h> 21#include <sys/time.h> 22#include <sys/timex.h> 23#include <string.h> 24#include <signal.h> 25#include "../kselftest.h" 26 27/* clear NTP time_status & time_state */ 28int clear_time_state(void) 29{ 30 struct timex tx; 31 int ret; 32 33 /* 34 * We have to call adjtime twice here, as kernels 35 * prior to 6b1859dba01c7 (included in 3.5 and 36 * -stable), had an issue with the state machine 37 * and wouldn't clear the STA_INS/DEL flag directly. 38 */ 39 tx.modes = ADJ_STATUS; 40 tx.status = STA_PLL; 41 ret = adjtimex(&tx); 42 43 tx.modes = ADJ_STATUS; 44 tx.status = 0; 45 ret = adjtimex(&tx); 46 47 return ret; 48} 49 50/* Make sure we cleanup on ctrl-c */ 51void handler(int unused) 52{ 53 clear_time_state(); 54 exit(0); 55} 56 57 58int main(void) 59{ 60 struct timex tx; 61 struct timespec ts; 62 time_t next_leap; 63 int count = 0; 64 65 setbuf(stdout, NULL); 66 67 signal(SIGINT, handler); 68 signal(SIGKILL, handler); 69 printf("This runs for a few minutes. Press ctrl-c to stop\n"); 70 71 clear_time_state(); 72 73 74 /* Get the current time */ 75 clock_gettime(CLOCK_REALTIME, &ts); 76 77 /* Calculate the next possible leap second 23:59:60 GMT */ 78 next_leap = ts.tv_sec; 79 next_leap += 86400 - (next_leap % 86400); 80 81 for (count = 0; count < 20; count++) { 82 struct timeval tv; 83 84 85 /* set the time to 2 seconds before the leap */ 86 tv.tv_sec = next_leap - 2; 87 tv.tv_usec = 0; 88 if (settimeofday(&tv, NULL)) { 89 printf("Error: You're likely not running with proper (ie: root) permissions\n"); 90 return ksft_exit_fail(); 91 } 92 tx.modes = 0; 93 adjtimex(&tx); 94 95 /* hammer on adjtime w/ STA_INS */ 96 while (tx.time.tv_sec < next_leap + 1) { 97 /* Set the leap second insert flag */ 98 tx.modes = ADJ_STATUS; 99 tx.status = STA_INS; 100 adjtimex(&tx); 101 } 102 clear_time_state(); 103 printf("."); 104 fflush(stdout); 105 } 106 printf("[OK]\n"); 107 return ksft_exit_pass(); 108}