Skip to contentSkip to conversation

Bug in select_tut

DISCUSSION Michael Kerrisk 1 participant 3 messages Jan 25, 2009 – Jan 26, 2009 3 messages not in the archive Man-pages: manual pages for Linux -- Sections 2, 3, 4, 5, and 7

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

#2 lore raw

Hi Sebastian,

Quoted 19 lines · Sebastian Kienzl

Hello!

There's a bug in the select_tut man-page in the chapter "Combining Signal and Data Events", which should illustrate pselect()-usage.

See the attachments for detailed information, proof-code and a proposed fix.

Regards,
Seb.

/*
This is a demonstration of how the code provided
in the Linux man-page select_tut(2) / "Combining Signal and Data Events" for counting SIGCHLD-events is not correct.

The problem is that the example-code assumes that
normal signals get queued somehow, which is not the case; quote from signal(7):

Quoted 8 lines

"By contrast, if multiple instances of a standard signal are delivered while that signal is currently blocked, then only one instance is queued."

Bottom line:

Setting a global flag when a signal has occured will do the job and that's what pselect() is intended for -- but counting the occurences of a standard signal as shown in the example DOES NOT WORK.

Thanks for your very thorough report. I agree that the example in its current form seems to be confused. (And indeed, there are many things taht I do not really like about this page, and I plan to clean some of them up.)

Quoted 5 lines

Compile and run this file to see how the example code will result in zombies if multiple SIGCHLDs are delivered at the same time;
compile with -DCORRECT to get the correct solution for this case.

See select_tut-badcount-fix.patch for a proposal to fix the documentation,.

However, what I am inclined to do is fix the program, rather than the text. I will send you a revised version in a moment; please take a look at it.

Cheers,

Michael

Signature · 9 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git
man-pages online: http://www.kernel.org/doc/man-pages/online_pages.html
Found a bug? http://www.kernel.org/doc/man-pages/reporting_bugs.html
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#3 lore raw
In reply to a message not in the archive

Hello Sebastian,

Quoted 10 lines · Sebastian Kienzl

Hello!

There's a bug in the select_tut man-page in the chapter "Combining Signal and Data Events", which should illustrate pselect()-usage.

See the attachments for detailed information, proof-code and a proposed fix.

Regards,
Seb.

What do you think of the revised (but still incomplete) program below?

Cheers,

Michael

       static volatile sig_atomic_t got_SIGCHILD = 0;

       void
       child_sig_handler(int sig)
       {
           got_SIGCHILD = 1;
       }

       int
       main(int argc, char *argv[])
       {
           sigset_t sigmask, empty_mask;
           struct sigaction sa;
           fd_set readfs, writefds, exceptfds;
           int r;

           sigemptyset(&sigmask);
           sigaddset(&sigmask, SIGCHLD);
           if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) {
               perror("sigprocmask");
               exit(EXIT_FAILURE);
           }

           sa.sa_flags = 0;
           sa.sa_handler = child_sig_handler;
           sigemptyset(&sa.sa_mask);
           if (sigaction(SIGCHILD, &sa, NULL) == -1) {
               perror("sigaction");
               exit(EXIT_FAILURE);
           }

           sigemptyset(empty_mask);

           for (;;) {          /* main loop */
               /* Initialize readfds, writefds, and exceptfds
                  before the pselect() call. (Code omitted.) */

               r = pselect(nfds, &readfs, &writefds, &exceptfd,
                           0, &empty_mask);
               if (r == -1 && errno != EINTR) {
                   /* Handle error */
               }

               if (got_SIGCHILD) {
                   got_SIGCHILD = 0;

                   /* Handle signalled event here; e.g., wait() for all
                      terminated children. (Code omitted.) */
               }

               /* main body of program */
           }
       }

--
To unsubscribe from this list: send the line "unsubscribe linux-man" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): [email protected]

#5 lore raw
Quoted 8 lines · Michael Kerrisk

Hello Sebastian,

Quoted 5 lines · Sebastian Kienzl

Hello!

There's a bug in the select_tut man-page in the chapter "Combining Signal and Data Events", which should illustrate pselect()-usage.

Quoted 8 lines
Quoted 5 lines

See the attachments for detailed information, proof-code and a proposed fix.

Regards,
Seb.

What do you think of the revised (but still incomplete) program below?

Hmmm -- obviously, s/SIGCHILD/SIGCHLD/ throughout the example code I sent earlier.

Cheers,

Michael

Quoted 56 lines

Michael

      static volatile sig_atomic_t got_SIGCHILD = 0;

      void
      child_sig_handler(int sig)
      {
          got_SIGCHILD = 1;
      }

      int
      main(int argc, char *argv[])
      {
          sigset_t sigmask, empty_mask;
          struct sigaction sa;
          fd_set readfs, writefds, exceptfds;
          int r;

          sigemptyset(&sigmask);
          sigaddset(&sigmask, SIGCHLD);
          if (sigprocmask(SIG_BLOCK, &sigmask, NULL) == -1) {
              perror("sigprocmask");
              exit(EXIT_FAILURE);
          }

          sa.sa_flags = 0;
          sa.sa_handler = child_sig_handler;
          sigemptyset(&sa.sa_mask);
          if (sigaction(SIGCHILD, &sa, NULL) == -1) {
              perror("sigaction");
              exit(EXIT_FAILURE);
          }

          sigemptyset(empty_mask);

          for (;;) {          /* main loop */
              /* Initialize readfds, writefds, and exceptfds
                 before the pselect() call. (Code omitted.) */

              r = pselect(nfds, &readfs, &writefds, &exceptfd,
                          0, &empty_mask);
              if (r == -1 && errno != EINTR) {
                  /* Handle error */
              }

              if (got_SIGCHILD) {
                  got_SIGCHILD = 0;

                  /* Handle signalled event here; e.g., wait() for all
                     terminated children. (Code omitted.) */
              }

              /* main body of program */
          }
      }
Signature · 9 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git
man-pages online: http://www.kernel.org/doc/man-pages/online_pages.html
Found a bug? http://www.kernel.org/doc/man-pages/reporting_bugs.html
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html