forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.2 KiB
108 lines
2.2 KiB
/* Demo leapsecond deadlock |
|
* by: John Stultz ([email protected]) |
|
* (C) Copyright IBM 2012 |
|
* (C) Copyright 2013, 2015 Linaro Limited |
|
* Licensed under the GPL |
|
* |
|
* This test demonstrates leapsecond deadlock that is possible |
|
* on kernels from 2.6.26 to 3.3. |
|
* |
|
* WARNING: THIS WILL LIKELY HARD HANG SYSTEMS AND MAY LOSE DATA |
|
* RUN AT YOUR OWN RISK! |
|
* To build: |
|
* $ gcc leapcrash.c -o leapcrash -lrt |
|
*/ |
|
|
|
|
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <time.h> |
|
#include <sys/time.h> |
|
#include <sys/timex.h> |
|
#include <string.h> |
|
#include <signal.h> |
|
#include "../kselftest.h" |
|
|
|
/* clear NTP time_status & time_state */ |
|
int clear_time_state(void) |
|
{ |
|
struct timex tx; |
|
int ret; |
|
|
|
/* |
|
* We have to call adjtime twice here, as kernels |
|
* prior to 6b1859dba01c7 (included in 3.5 and |
|
* -stable), had an issue with the state machine |
|
* and wouldn't clear the STA_INS/DEL flag directly. |
|
*/ |
|
tx.modes = ADJ_STATUS; |
|
tx.status = STA_PLL; |
|
ret = adjtimex(&tx); |
|
|
|
tx.modes = ADJ_STATUS; |
|
tx.status = 0; |
|
ret = adjtimex(&tx); |
|
|
|
return ret; |
|
} |
|
|
|
/* Make sure we cleanup on ctrl-c */ |
|
void handler(int unused) |
|
{ |
|
clear_time_state(); |
|
exit(0); |
|
} |
|
|
|
|
|
int main(void) |
|
{ |
|
struct timex tx; |
|
struct timespec ts; |
|
time_t next_leap; |
|
int count = 0; |
|
|
|
setbuf(stdout, NULL); |
|
|
|
signal(SIGINT, handler); |
|
signal(SIGKILL, handler); |
|
printf("This runs for a few minutes. Press ctrl-c to stop\n"); |
|
|
|
clear_time_state(); |
|
|
|
|
|
/* Get the current time */ |
|
clock_gettime(CLOCK_REALTIME, &ts); |
|
|
|
/* Calculate the next possible leap second 23:59:60 GMT */ |
|
next_leap = ts.tv_sec; |
|
next_leap += 86400 - (next_leap % 86400); |
|
|
|
for (count = 0; count < 20; count++) { |
|
struct timeval tv; |
|
|
|
|
|
/* set the time to 2 seconds before the leap */ |
|
tv.tv_sec = next_leap - 2; |
|
tv.tv_usec = 0; |
|
if (settimeofday(&tv, NULL)) { |
|
printf("Error: You're likely not running with proper (ie: root) permissions\n"); |
|
return ksft_exit_fail(); |
|
} |
|
tx.modes = 0; |
|
adjtimex(&tx); |
|
|
|
/* hammer on adjtime w/ STA_INS */ |
|
while (tx.time.tv_sec < next_leap + 1) { |
|
/* Set the leap second insert flag */ |
|
tx.modes = ADJ_STATUS; |
|
tx.status = STA_INS; |
|
adjtimex(&tx); |
|
} |
|
clear_time_state(); |
|
printf("."); |
|
fflush(stdout); |
|
} |
|
printf("[OK]\n"); |
|
return ksft_exit_pass(); |
|
}
|
|
|