Menu

How to timeout an ipstream process

Help
Brian G
2004-12-02
2013-01-20
  • Brian G

    Brian G - 2004-12-02

    Is it possible to timeout an ipstream process after a defined period?  I am issuing a lpd print queue command and if there is not a response within 5 seconds I want to stop the ipstream process and then call an error routine.

     
    • Jonathan Wakely

      Jonathan Wakely - 2004-12-04

      PStreams doesn't currently provide a way of setting a timeout, but you can use an alarm signal to interrupt the process while it's waiting for data. I hope this program demonstrates the idea:

      #include <signal.h>
      #include <time.h>
      #include <unistd.h>
      #include <pstream.h>

      // whether we timed out or not
      volatile sig_atomic_t timed_out = 0;

      void signal_handler(int)
      {
          timed_out = 1;
      }

      int main()
      {
          using namespace redi;

          sigset_t block_mask;
          sigemptyset(&block_mask);

          struct sigaction action;
          action.sa_handler = signal_handler;
          action.sa_mask = block_mask;
          action.sa_flags = 0;

          // set signal handler for SIGALRM
          sigaction(SIGALRM, &action, 0);

          srand(time(0));
          int timeout = rand() % 4 + 1;
          std::cout << "Time out in " << timeout << " seconds" << std::endl;

          ipstream child("sleep 2 && echo finished");

          alarm(timeout); // raise SIGALRM after timeout seconds

          std::string s;
          std::getline(child, s);

          if (timed_out)
          {
              std::cerr << "Timed out\n";
              child.rdbuf()->kill();
              return EXIT_FAILURE;
          }
          else
          {
              std::cout << s << std::endl;
              return EXIT_SUCCESS;
          }
      }

      If getline() does not return before the alarm it will be interrupted, timed_out will be set, control will return to the main function and the error handling will be run.

      I hadn't planned to make PStreams include this functionality as it might interfere with other signal handling in the program, but since using it would be optional I will reconsider it.

       
    • Jonathan Wakely

      Jonathan Wakely - 2004-12-05

      I should add that the example program is incomplete. In a real program you would have to reset the alarm to prevent it timing out after a successful read. You should also restore the default action for the SIGALRM signal.

       
    • Brian G

      Brian G - 2004-12-06

      Thanks for the response.  A further question:

      I am using AIX and its qchk command.

      A successful qchk command displays soething similar to the following:

      qchk -P R1129
      Queue   Dev   Status    Job Files              User         PP %   Blks  Cp Rnk
      ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
      R1129   hp4mv READY   
      R1129: JetDirect lpd: no jobs queued on the port Auto

      A failed qchk command looks similar to the following:

      qchk -P Q1111
      Queue   Dev   Status    Job Files              User         PP %   Blks  Cp Rnk
      ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
      Q1111   hp4si READY   

      : (WARNING) 0781-375 Connection to server failed.
      rembak: errno = 81: A route to the remote host is not available.
      Q1111   queue HOST_DOWN

      I use the following code to get the output:

      ipstream qchk("qchk -P Q1111");
      string buffer;

      while ( getline(qchk, buffer) ) {
         cout << buffer << endl;
      }

      A failed qchk command immediately displays:

      qchk -P Q1111
      Queue   Dev   Status    Job Files              User         PP %   Blks  Cp Rnk
      ------- ----- --------- --- ------------------ ---------- ---- -- ----- --- ---
      Q1111   hp4si READY

      and then after 45 seconds displays the remainder of the text (: (WARNING) ... ).

      The following code still waits 45 seconds (the remaining code is identical to that which you provided):

      ...
      ...
      while ( getline(qchk, buffer) )
         {
            if (timed_out)
            {
               cerr << "Timed out\n";
               qchk.rdbuf()->kill(9);
            }
            else
            {
               qchkVct.push_back (buffer);
            }
         }
         if (! timed_out)
         {
            copy(qchkVct.begin(), qchkVct.end(), ostream_iterator<string>(cout, "\n"));
         }

      Would you know why it still waiting the 45 seconds?

       
    • Jonathan Wakely

      Jonathan Wakely - 2004-12-08

      Hi Brian,

      I've never tested PStreams on AIX, so although it *should* work exactly the same I can't guarantee it.

      I'm not sure why your program is still pausing, but I'll think about it and see if I can figure it out...

      jon

       

Log in to post a comment.