Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Jul 2008 17:09:20 -0400
From:      "Michael B Allen" <ioplex@gmail.com>
To:        "=?ISO-8859-1?Q?Mikko_Ty=F6l=E4j=E4rvi?=" <mbsd@pacbell.net>
Cc:        freebsd-hackers <freebsd-hackers@freebsd.org>
Subject:   Re: Pls sanity check my semtimedop(2) implementation
Message-ID:  <78c6bd860807131409v6e34478ameda1390b9eb2333f@mail.gmail.com>
In-Reply-To: <Pine.OSX.4.64.0807131240250.594@mbook.home>
References:  <78c6bd860807130813p4c28f930g1f3094241aa1f1b1@mail.gmail.com> <Pine.OSX.4.64.0807131240250.594@mbook.home>

next in thread | previous in thread | raw e-mail | index | archive | help
On 7/13/08, Mikko Ty=F6l=E4j=E4rvi <mbsd@pacbell.net> wrote:
> On Sun, 13 Jul 2008, Michael B Allen wrote:
>
>
> > Hi,
> >
> > Below is a semtimedop(2) implementation that I'm using for FreeBSD. I
> > was hoping someone could look it over and tell me if they think the
> > implementation is sound.
> >
> > The code seems to work ok but when stressing the FreeBSD build of my ap=
p
> > I have managed to provoke errors related to concurrency (usually when a
> > SIGALRM goes off). The Linux build works flawlessesly so I'm wondering
> > about this one critical function that is different.
> >
>
>  At the very least you need to check errno when semop() returns -1.
>  Unless it is EINTR, you have other problems.
>
>  Also, if there is any other code using the timer across this function
>  call, you have race conditions between changing the signal handler and
>  setting the timer.  Even if there is no other use of the timer across
>  this function, resetting the signal handler before disarming the timer
>  leaves you open to the signal being handled by the default handler
>  which will make the process exit.

Hi Mikko,

So if some other code uses setitimer(2) for whatever reason, then I
have the potential for a race. I'm not aware of any other such
instances of setitimer but my app is actually a plugin for a larger
application so I can't entirely rule out the possibility.

Is there any facility for creating a stateful timer so that I don't
run into this problem?

Can anyone provide the basis for an alternative implementation?

Should I use select(2) instead?

Mike

> > Is there any reason why I would want to use ITIMER_VIRTUAL /
> > SIGVTALRM instead of ITIMER_REAL / SIGALRM?
> >
> > Or perhaps I should be using a different implementation entirely?
> >
> > Mike
> >
> > int
> > _semtimedop(int semid,
> >      struct sembuf *array,
> >      size_t nops,
> >      struct timespec *_timeout)
> > {
> >  struct timeval timeout, before, after;
> >  struct itimerval value, ovalue;
> >  struct sigaction sa, osa;
> >  int ret;
> >
> >  if (_timeout) {
> >      timeout.tv_sec =3D _timeout->tv_sec;
> >      timeout.tv_usec =3D _timeout->tv_nsec / 1000;
> >
> >      if (gettimeofday(&before, NULL) =3D=3D -1) {
> >          return -1;
> >      }
> >
> >      memset(&value, 0, sizeof value);
> >      value.it_value =3D timeout;
> >
> >      memset(&sa, 0, sizeof sa);
> >      /* signal_print writes the signal info to a log file
> >       */
> >      sa.sa_sigaction =3D signal_print;
> >      sa.sa_flags =3D SA_SIGINFO;
> >      sigemptyset(&sa.sa_mask);
> >      sigaction(SIGALRM, &sa, &osa);
> >
> >      if (setitimer(ITIMER_REAL, &value, &ovalue) =3D=3D -1) {
> >          sigaction(SIGALRM, &osa, NULL);
> >          return -1;
> >      }
> >  }
> >
> >  ret =3D semop(semid, array, nops);
> >
> >  if (_timeout) {
> >      sigaction(SIGALRM, &osa, NULL);
> >
> >      if (setitimer(ITIMER_REAL, &ovalue, NULL) =3D=3D -1) {
> >          return -1;
> >      }
> >  }
> >
> >  if (ret =3D=3D -1) {
> >      if (_timeout) {
> >          struct timeval elapsed;
> >
> >          if (gettimeofday(&after, NULL) =3D=3D -1) {
> >              return -1;
> >          }
> >
> >          _timeval_diff(&after, &before, &elapsed);
> >
> >          if (timercmp(&elapsed, &timeout, >=3D))
> >              errno =3D EAGAIN;
> >      }
> >
> >      return -1;
> >  }
> >
> >  return 0;
> > }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?78c6bd860807131409v6e34478ameda1390b9eb2333f>