Re: pingflood.c

From: Jeffrey Hutzelman (jhutz+@cmu.edu)
Date: Mon May 18 1998 - 12:51:27 PDT

  • Next message: Leendert van Doorn: "Re: NFS shell"

    > The reason that this works is because many platforms implement sleep(2)
    > as:
    >
    > alarm(seconds);
    > sigsuspend(...);
    >
    >
    > This is implementation is done in Solaris, etc.  I have implemented my
    > own sleep function because when using threads under Solaris, messing with
    > signals is a bad proposition.  So:
    
    Ummm...  I don't know what version of Solaris you're using, but
    as of 2.5, sleep(3c) is MT-Safe.  So long as you're not playing with
    SIGALRM yourself, it works as expected in multi-threaded as well as
    single-threaded applications.
    
    > void mysleep(int seconds)
    > {
    >         struct timeval  tv;
    >
    >         tv.tv_sec=seconds;
    >         tv.tv_usec=0;
    >
    >         select(0,NULL,NULL,NULL,&tv);
    > }
    >
    > The code above should be portable to every platform that supports the
    > standard select(2) semantics.  It allows for subsecond precision too.
    > This implementation isn't subject to signal dainbrammage either.
    
    This, on the other hand, has the problem that the sleep can
    terminate prematurely if any signal is delivered - select(3c) will
    exit with EINTR in that case.  Unfortunately, select is not
    guaranteed to tell you how much time is remaining, so you must
    keep track of when to wake up and keep sleeping until that time
    arrives.
    
    Note that neither sleep(3c) nor select(3c) is a system call on Solaris.
    As you pointed out, sleep() is implemented in terms of alarm(2) and
    SIGALRM, on Solaris and most other platforms as well.  On many SysV-ish
    platforms, including Solaris, select() is implemented in terms of
    poll(), which has only millisecond accuracy.
    
    
    Overall, the best approach for programs like ping would be to use
    select, with a loop to trap interruptions:
    
    void safe_sleep(int seconds)
    {
      time_t when, now;
      struct timeval tv;
    
      when = time(0) + seconds;
      for (;;) {
        now = time(0);
        if (now >= when) return;
        tv.tv_sec  = when - now;
        tv.tv_usec = 0;
        if (select(0, 0, 0, 0, &tv) >= 0 || errno != EINTR) return;
      }
    }
    
    -- Jeffrey T. Hutzelman (N3NHS) <jhutz+@cmu.edu>
       Systems Programmer
       School of Computer Science - Research Computing Facility
       Carnegie Mellon University - Pittsburgh, PA
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:54:13 PDT