Bug 6443 - setitimer() should reject non-canonical arguments
Summary: setitimer() should reject non-canonical arguments
Status: CLOSED WILL_FIX_LATER
Alias: None
Product: Timers
Classification: Unclassified
Component: Interval Timers (show other bugs)
Hardware: i386 Linux
: P2 normal
Assignee: Thomas Gleixner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-04-25 20:35 UTC by Michael Kerrisk
Modified: 2007-09-10 04:36 UTC (History)
0 users

See Also:
Kernel Version: 2.6.16
Subsystem:
Regression: ---
Bisected commit-id:


Attachments

Description Michael Kerrisk 2006-04-25 20:35:11 UTC
Most recent kernel where this bug did not occur: all kernels
Distribution: n/a
Hardware Environment: x86 (and probably all others)
Software Environment: n/a

Problem Description:
The POSIX.1 specification of setitimer() says that the call should fail
with the error EINVAL if the microsecond (tv_usec) components of the
value argument are not "canonical", that is:

    0 <= tv_usec < 1000

FreeBSD 6.0 and Solaris 8 (the only other implementations that I 
have recently tested) honour the POSIX.1 requirement.

On Linux, a non-canonical tv_usec value is instead normalised
so that if, say, tv_usec is 2300000, then the 2000000 microseconds
are added to the seconds (tv_sec) value (as 2 seconds), and the 
tv_usec value is taken as 300000 microseconds.  This is not
POSIX.1 conformant.

Steps to reproduce:

The behaviour can be demonstrated with the program below.

/* t_setitimer.c

   A demonstration of the use of (real time) timers.

   Usage: real_timer [secs [usecs [int-secs [int-usecs]]]]
             Defaults: 2      0        0         0

   The command-line arguments are the second and microsecond
   settings for the timers initial value and interval.
*/


#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include "lp_hdr.h"

static volatile sig_atomic_t gotAlarm = 0;
                        /* Set non-zero on receipt of SIGALRM */

static void
sigalrmHandler(int sig)
{
    gotAlarm = 1;
} /* sigalrmHandler */

int
main(int argc, char *argv[])
{
    struct itimerval itv;
    int maxSigs;            /* # of signals to catch before exiting */
    int sigCnt;             /* # of signals so far caught */
    struct sigaction sa;

    if (argc > 1 && strcmp(argv[1], "--help") == 0)
        usageErr("%s [secs [usecs [int-secs [int-usecs]]]]\n", argv[0]);

    sigCnt = 0;

    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = sigalrmHandler;
    if (sigaction(SIGALRM, &sa, NULL) == -1) errExit("sigaction");

    /* Set timer from the command-line arguments */

    itv.it_value.tv_sec =  (argc > 1) ?
                                getLong(argv[1], 0, "secs") : 2;
    itv.it_value.tv_usec = (argc > 2) ?
                                getLong(argv[2], 0, "usecs") : 0;
    itv.it_interval.tv_sec = (argc > 3) ?
                                getLong(argv[3], 0, "int-secs") : 0;
    itv.it_interval.tv_usec = (argc > 4) ?
                                getLong(argv[4], 0, "int-usecs") : 0;

    /* Exit after 3 signals, or on first signal if interval is 0 */

    maxSigs = (itv.it_interval.tv_sec == 0 &&
                itv.it_interval.tv_usec == 0) ? 1 : 3;

    if (setitimer(ITIMER_REAL, &itv, 0) == -1) errExit("setitimer");

    sigCnt = 0;

    for (;;) {

        while (1) {
            if (gotAlarm) {             /* Did we get a signal? */
                gotAlarm = 0;
                printf("Got signal\n");

                sigCnt++;
                if (sigCnt >= maxSigs) {
                    printf("That's all folks\n");
                    exit(EXIT_SUCCESS);
                }
            }
        }

    }
}
Comment 1 Michael Kerrisk 2006-04-26 11:19:05 UTC
Oops, the following line in the report:

    0 <= tv_usec < 1000

Should of course have been:

    0 <= tv_usec < 1000000
Comment 2 Thomas Gleixner 2006-04-26 11:20:47 UTC
That's a known problem. Please see:

http://kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=7d99b7d634d81bb372e03e4561c80430aa4cfac2

The check will be POSIX compliant after the grace period.

Thanks,

 tglx
Comment 3 Michael Kerrisk 2006-04-26 11:31:52 UTC
Thnaks -- that was quick turnaround.
Comment 4 Thomas Gleixner 2007-09-10 04:00:15 UTC
The grace period is over and the interface is now correct.
Comment 5 Michael Kerrisk 2007-09-10 04:36:12 UTC
Thanks Thomas.  Yes, I spotted the fix went in 2.6.22, but forgot to close this report.  Man page is already updated with the change ;-).

Note You need to log in before you can comment on or make changes to this bug.