setitimer with ITIMER_VIRTUAL has no effect on 64-bit kernel

Originator:Per.Mildner.usenet
Number:rdar://9336975 Date Originated:26-Apr-2011 10:49 AM
Status:Closed Resolved:
Product:Mac OS X Product Version:10.6.7
Classification:Serious bug Reproducible:Always
 
Summary:

setitimer with ITIMER_VIRTUAL has no effect on 64-bit kernel Mac OS X
10.6.7. ITIMER_REAL works.

Steps to Reproduce:

See attached program.

Expected Results:

expect SIGVTALRM to happen, i.e. V is written by test program until
interrupted by CTRL+C.

Transcript from a machine (with 32-bit kernel) where it works as it
should (real user name replaced with xxx):

sekretariat:~ xxx$ gcc -version
i686-apple-darwin10-gcc-4.2.1: no input files
sekretariat:~ xxx$ gcc -Wall -Werror timer.c -o timer && ./timer
VVVVVVVVVVVVVVVVVVVVVVVVV^C
sekretariat:~ xxx$ uname -a
Darwin sekretariat.local 10.7.0 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386
sekretariat:~ xxx$ date
Tue Apr 19 16:29:09 CEST 2011

Actual Results:
SIGVTALRM is never signalled, i.e. V is never written

Transcript from failing machine (with 64-bit kernel):
balrog:PrologTestFiles xxx$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

balrog:PrologTestFiles xxx$ gcc -Wall -Werror timer.c -o timer && ./timer
^C
balrog:PrologTestFiles xxx$ uname -a
Darwin balrog.local 10.7.0 Darwin Kernel Version 10.7.0: Sat Jan 29 15:16:10 PST 2011; root:xnu-1504.9.37~1/RELEASE_X86_64 x86_64
balrog:PrologTestFiles xxx$ date
Di 19 Apr 2011 15:39:53 CEST

Regression:

This seems to work with 32-bit kernels. Running on a VMWare guest (Mac
OS X Server 10.6.7) I can reproduce the problem when it boots with
64-bit kernel but the problem goes away when I reboot the same VMWare
guest with a 32-bit kernel (even without recompiling the timer
executable). Note that the above systems refer to real machines, not
VMWare guests.

Notes:

This is a serious bug for us, even though there is a workaround (use 32-bit kernels), since our product (a programming language runtime) is embedded in our customers products and we have no way of informing the end users of the workaround.

/* timer.c BEGIN */
/*

This program demonstrates a bug where setitimer ITIMER_VIRTUAL does
not seem to have any effect (seen on Mac OS X 10.6.7).

[PM] Slightly modified from a program found on the net, originally
written by Marc Feeley.

Compile and run as

 gcc -Wall -Werror timer.c -o timer && ./timer

it should write one V on stdout every 1/10 of a second.

or

 gcc -DITIMER_SECS=1 timer.c -o timer && ./timer

it should write one V on stdout about once every second.

When the bug occurs the program just hangs.

The program can be built to use ITIMER_REAL instead, with

 gcc -DUSE_ITIMER_REAL timer.c -o timer && ./timer

this has not been seen to hang.

*/

#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#ifndef ITIMER_SECS
#define ITIMER_SECS 0
#endif
#ifndef ITIMER_USECS
#define ITIMER_USECS 100000
#endif  /* ITIMER_USECS */

#define CHECK(EXPR) do{                         \
   if ((EXPR) == -1) {                         \
     int e = errno;                            \
     fprintf(stderr, "%s:%d ERROR errno=%d\n", \
             __FILE__, (int)__LINE__, e);      \
     fflush(stderr);                           \
     abort();                                  \
   }                                           \
 } while (0)

void heartbeat_interrupt_handler (int sig)
{
#ifdef USE_ITIMER_REAL
write (STDOUT_FILENO, "R", 1);
#else
write (STDOUT_FILENO, "V", 1);
#endif
}

int main (int argc, char *argv[])
{
struct itimerval tv;
int secs = ITIMER_SECS;
int usecs = ITIMER_USECS;

#ifdef USE_ITIMER_REAL
int HEARTBEAT_ITIMER = ITIMER_REAL;
int SIG = SIGALRM;
#else
int HEARTBEAT_ITIMER = ITIMER_VIRTUAL;
int SIG = SIGVTALRM;
#endif

struct sigaction act;
act.sa_handler = heartbeat_interrupt_handler;
act.sa_flags = 0;
CHECK(sigemptyset(&act.sa_mask));
CHECK(sigaction(SIG, &act, 0));

tv.it_interval.tv_sec  = secs;
tv.it_interval.tv_usec = usecs;
tv.it_value.tv_sec     = secs;
tv.it_value.tv_usec    = usecs;
CHECK(setitimer(HEARTBEAT_ITIMER, &tv, 0));

for (;;)
  {
    /* keep CPU 100% busy */
  }

return 0;
}

/* timer.c END */

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!