Index: contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c =================================================================== --- contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c +++ contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c @@ -50,6 +50,15 @@ /* Nothing. */ } +static int got_info; +static void +info_handler(int signo __unused) +{ + + got_info = 1; +} + + ATF_TC(nanosleep_basic); ATF_TC_HEAD(nanosleep_basic, tc) { @@ -176,12 +185,90 @@ atf_tc_fail("signal did not interrupt nanosleep(2)"); } +ATF_TC(nanosleep_eintr); +ATF_TC_HEAD(nanosleep_eintr, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test [EINTR] for nanosleep(2)"); + atf_tc_set_md_var(tc, "timeout", "7"); +} + +ATF_TC_BODY(nanosleep_eintr, tc) +{ + struct sigaction act; + struct timespec tso, ts; + pid_t pid, floodpid; + int sta; + + /* + * Test that [EINTR] properly handles rmtp for nanosleep(2). + */ + pid = fork(); + + ATF_REQUIRE(pid >= 0); + + got_info = 0; + + if (pid == 0) { + act.sa_handler = info_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; /* Don't allow restart. */ + ATF_REQUIRE(sigaction(SIGINFO, &act, NULL) == 0); + + tso.tv_sec = 5; + tso.tv_nsec = 0; + + ts.tv_sec = tso.tv_sec; + ts.tv_nsec = tso.tv_nsec; + + errno = 0; + while (nanosleep(&ts, &ts) != 0) { + if (errno == EINTR && got_info == 1) { + ATF_REQUIRE_MSG(timespeccmp(&ts, &tso, <=), + "errno: %d got_info: %d " + "ts=%0.9f should be <= tso=%0.9f\n", + errno, got_info, + ts.tv_sec + ts.tv_nsec / 1e9, + tso.tv_sec + tso.tv_nsec / 1e9); + got_info = 0; + errno = 0; + continue; + } + _exit(EXIT_FAILURE); + } + + if (errno != 0) + _exit(EXIT_FAILURE); + + _exit(EXIT_SUCCESS); + } + + /* Fork a process to signal flood the child. */ + + floodpid = fork(); + + ATF_REQUIRE(floodpid >= 0); + + if (floodpid == 0) { + while (1) { + (void)kill(pid, SIGINFO); + (void)usleep(50000); + } + } + + (void)waitpid(pid, &sta, 0); + (void)kill(floodpid, SIGKILL); + + if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) + atf_tc_fail("nanosleep(2) handled rtmp incorrectly"); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, nanosleep_basic); ATF_TP_ADD_TC(tp, nanosleep_err); ATF_TP_ADD_TC(tp, nanosleep_sig); + ATF_TP_ADD_TC(tp, nanosleep_eintr); return atf_no_error(); } Index: sys/kern/kern_time.c =================================================================== --- sys/kern/kern_time.c +++ sys/kern/kern_time.c @@ -563,7 +563,8 @@ } while (error == 0 && is_abs_real && td->td_rtcgen == 0); td->td_rtcgen = 0; if (error != EWOULDBLOCK) { - TIMESEL(&sbtt, tmp); + if (TIMESEL(&sbtt, tmp)) + sbtt += tc_tick_sbt; if (sbtt >= sbt) return (0); if (error == ERESTART)