Need to implement C++ exception handler to limit return time

I want to implement a robost C++ exception handler that is initiated after several seconds of no response.  The code invokes a command like script via unix "popen" command.  If the response is not returned in 5-seconds, I want to invoke the exeception handler which will return with an error:  Cod snippet:

       if ( cmd = popen (Cmd.c_str(), "r") ) != 0)
      {
               fgets (line, MAX_LINE, data);
      }
     else
    {
         //  ERROR
    }
LVL 1
sdrussAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

efnCommented:
C++ doesn't have facilities to limit the time spent in a called function.  You will either have to call a function that limits its own time or use multiple threads, which is also outside the scope of the C++ language.  Somebody here could probably help you pursue either of these, but the question would be more appropriate in a UNIX topic area.
0
itsmeandnobodyelseCommented:
Which statement do you want to timeout? The popen or the fgets?
0
HappyCactusCommented:
use signals and "alarm":

http://linux.die.net/man/2/alarm

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
 
typedef void (*sighandler_t)(int);
void alarm_hand()
{
 // your "exception handler" here
}

// ...
 
int main(int argc, char **argv)
{
 int res;
 int alarm_timeout, select_timeout;
 fd_set fset;
 struct timeval tv;
 struct sigaction act;

  // ...

 /* signal definition */
 act.sa_handler = alarm_hand;
 sigemptyset(&act.sa_mask);
 /* this flag should restart the interrupted syscall */
 act.sa_flags = SA_RESTART;
 sigaction(SIGALRM, &act, NULL);
 
 /* starting SIGALRM countdown */
 alarm(alarm_timeout);
 
    if ( cmd = popen (Cmd.c_str(), "r") ) != 0)
      {
               fgets (line, MAX_LINE, data);
      }
     else 
    {
         //  ERROR
    } 

  // ... etc etc ...

Open in new window

0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

evilrixSenior Software Engineer (Avast)Commented:
>> use signals and "alarm":
You can use alarm to generate a message but once the signal handler has finished control will resume from where it left, back in the popen function. Since popen will continue until the process it started terminates what you probably want to do is kill the process you started in the signal handler. Unfortunately, popen doesn't return a pid so you'll probably have to resort to using posix_spawn, which does give you a pid and also allows you to map file descriptors in your current process to file descriptors in your child process, thus emulating popen.

So, the idea is you spawn a new process with posix_spawn, save the pid for use by the signal handler and map the child processes stdout to a file descriptor to the end of a pipe in your current process. You then read from the pipe, which will give you the piped output from the child process. If/when the signal handler is called you send a terminate signal to your child process using the kill function. This will abort the posix_spawn and allow your main process to continue. Your signal handler will also output your error.

http://www.opengroup.org/onlinepubs/009695399/functions/posix_spawn.html
http://www.opengroup.org/onlinepubs/009695399/functions/kill.html
0
itsmeandnobodyelseCommented:
You accepted the wrong answer. Please do 'Request Attention' and let a Moderator reopen the question.

0
HappyCactusCommented:
evilrix,

I do not think that the author wanted to interrupt the popen but instead the fgets. The reason is, I think, that since popen is in effect a fork() followed by a execl(), it returns almost instantaneously. ITOH, fgets() needs to fill the buffer before returning, so it is reasonably that eventually the SIGALRM will interrupt the fgets().
Closing the pipe after the fgets should terminate the child process automatically.
0
evilrixSenior Software Engineer (Avast)Commented:
>>  The reason is, I think, that since popen is in effect a fork() followed by a execl(), it returns almost instantaneously
popen is piped output, it executes the command and captures the output. The process  started will continue until it's finished or until it's signalled to stop. You're right that popen returns immediately and I read back my previous post and I can see probably could have worded it better (posting when tired is a bad idea -- 5am starts are a killer :( ).

>> Closing the pipe after the fgets should terminate the child process automatically.
The point I was trying to make is that once the process is started by popen will continue and there is no way to stop it. Closing the file handle returned by popen doesn't stop the process, it just closes the file stream. If the process needs to be terminated you'll need the pid and you can't get this from popen.
0
HappyCactusCommented:
I think it "should" end the process because the process should receive the SIGPIPE signal. most application do not handle SIGPIPE by installing the proper signal handler, so the default action is to end the process: signal(3) on my macosx states:

 13    SIGPIPE      terminate process    write on a pipe with no reader

But, of course, you can find a process that handle the signal and do not end... in this case, you should end it in some other way, the best should kill it with SIGTERM or SIGQUIT or in some other "clean" way...
0
evilrixSenior Software Engineer (Avast)Commented:
>> you can find a process that handle the signal and do not end
Precisely. Plus SIGPIPE will only get generated if the child actually attempt to write to the pipe. This may not be the case.

>> the best should kill it with SIGTERM or SIGQUIT
Agreed, but to do that you need the pid and popen doesn't give you that.

Of course, this may all be moot if the askers process is actually decided to work in this way :)
0
HappyCactusCommented:
>>> you can find a process that handle the signal and do not end
> Precisely. Plus SIGPIPE will only get generated if the child actually attempt to write to the pipe. This may not be the > case.

I do not remember if closing the pipe will also raise SIGHUP...

>>> the best should kill it with SIGTERM or SIGQUIT
> Agreed, but to do that you need the pid and popen doesn't give you that.

maybe searching through the child process pid, but if you need the pid you'd better use explicitly a pipe() followed by fork() and execl()...

> Of course, this may all be moot if the askers process is actually decided to work in this way :)

of course ;-)
0
phoffricCommented:
Hey HappyCactus,
Remember we worked together on pipes running from main to child to grandchild? So, couldn't the main parent fork a child who does the popen (which as you already mentioned is likely implemented with a fork and execl). The child reads the popen and pumps what it gets to the main via the pipe. The timeout comes into play in the main using select on the pipe.

    int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
           http://linux.die.net/man/2/select

On a timeout the select can kill the child, or move onto other activities and retry later. Just thinking aloud here.
0
HappyCactusCommented:
Speaking for myself, I would implement it right in this way.
But I do not know what are the requirements of the author, sometimes my customers ask me a very simple implementation (I do not know why they think that simple works better...)
0
itsmeandnobodyelseCommented:
select with timeout would prevent the own process to be blocked on the pipe. But the child process never might be killed that way. On the other hand after killing the blocking child process from signal handler, the blocking wait automatically was released. So, the second seems the better choice.

Maybe the best would be to have a child process which itself was non-blocking and could be terminated by timeout.
0
phoffricCommented:
>> have a child process which itself was non-blocking and could be terminated by timeout.
popen returns fp; whereas select uses fd; but since after popen we read from stdin, maybe fd=0 for select will work. If so, then no need to have a parent fork a child that does the popen; maybe using this idea, just the main process can do the select on fd with a timeout. I'm assuming that popen will either return (error or success) without blocking. Do you think this assumption is correct?

>> select with timeout would prevent the own process to be blocked on the pipe.
>> But the child process never might be killed that way.
Not sure I understand. My thought was that the parent does a fork and read pipe from child; and then uses blocked select with timeout value on the pipe. If the parent process select times out, the parent would kill the child. What am I forgetting?
0
itsmeandnobodyelseCommented:
>>>> I do not know why they think that simple works better...

When simple things don't work *YOU* can say "It was too simple...". When complex things don't work *THEY* will say "we never wanted it that way ..."  ;-)
0
HappyCactusCommented:
phorrific,

you can use fileno() to have the file descriptor out of the FILE * (infacts, O.S. uses file descriptors as primary handle to access the file system services, while FILE streams are a layer higher than the O.S..)

itsmeandnobodyelse,

They always says "we never wanted it that way", even if the complex solution works...

0
phoffricCommented:
>> fileno()
Very good. So, do you all agree that the select timeout idea will work to identify a dead (or slow) popened program? Killing the popen program from within a single process may take a few more steps than just killing a child pid using a parent/child approach.
0
itsmeandnobodyelseCommented:
>>>> My thought was that the parent does a fork and read pipe from child;

In the initial q. the Asker said: "The code invokes a command like script via unix "popen" command". So it depends on the script whether there was some process which may hang for ever, right?
0
sdrussAuthor Commented:
evilrix: You are correct I made a mistake accepting the solution.  Thanks!  

I am partial to the solution using "select".  phoffric, how would I actually implement this based on this code snippet:  

      if ((Data = popen(Cmd.c_str(), "r")) != NULL)
      {
            INT4 jndx = 0;

            while (fgets(line, MAX_LINE, Data) != NULL)
            {
               if (ndx < MAX_LENGTH)
               {
                  Data[ndx++].assign(line);
               }
            }        
            pclose(Data);
         }
       
0
HappyCactusCommented:
It should be  something similar (not tested, maybe you must adjust something)
 if ((Data = popen(Cmd.c_str(), "r")) != NULL) 
      {
         fd_set fds;
         FD_ZERO(&fds);
         int fdnum = Data->fileno();
         struct timeval timeout;
         timeout.tv_sec = 3;     // 3 seconds timeout
         timeout.tv_usec = 0;
         
            INT4 jndx = 0;

            while (select (fdnum+1, &fds, 0, 0, &timeout) > 0) 
            {
               fgets(line, MAX_LINE, Data) != NULL)
               if (ndx < MAX_LENGTH)
               {
                  Data[ndx++].assign(line);
               }
            }         
            pclose(Data);
         }

Open in new window

0
phoffricCommented:
Two programs shown below.
The first is a dummy child program that accepts user input and it returns all lowercase letters.
The 2nd spawns and reads the stdout of the dummy program. If the user doesn't keep typing between lines in a timely manner, then this program times out.
However, what do want to do with the dummy program? You can kill it if you want. Since you don't have the pid, if the child script or program has a unique name, you can programmatically do a
    ps | grep program-name
and determine the pid; then do a kill pid (or kill -9 pid).
But what you do is another topic.
I don't believe it will be much of a step to add in the C++ touches so that you can fill up your Data string vector.


/////////////////////////////////////////////////
/* ConsoleUpToLow.c - adapted from Stevens
   "Advanced Programming in the Unix Environment" (Program 14.6) */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main() {
   int c;
   printf("Filter to convert UPPERCASE letters to lowercase\n");
   fflush( stdout );
   while( ( c = getchar() ) != EOF ) {
      if( isupper(c) )
         c = tolower(c);
      if( putchar(c) == EOF )
         perror("output error");
      if( c == '\n' )
         fflush( stdout );
   }
   printf("thank you and goodbye\n");
   exit(0);
}
/////////////////////////////////////////////////
/* popen_timeout.c - adapted from Stevens 
      "Advanced Unix Programming" Listing 16.2 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>

#define MAX_LENGTH 200

int main(int argc,char **argv) {
   int z; /* General status code */
   int f1=-1; /* Open fifo 1 */
   fd_set rxset; /* Read fd set */
   int nfds; /* Number of file descriptors */
   struct timeval tv; /* Timeout */

   char buf[MAX_LENGTH+1]; /* I/O Buffer */
   FILE *p1, *p2; /* Pipes from popen(3) */
   char * Cmd1 = "ls -l|tr '[a-z]' '[A-Z]'";
   char * Cmd = "./ConsoleUpToLow";
   int done = 0;

   /* Open pipe to ps(1) command for reading : */
   p1 = popen( Cmd ,"r");
   if ( !p1 ) {
      perror("popen(3)");
      return 13;
   }
   /* Obtain the underlying file descriptors : */
   f1 = fileno(p1);
   printf("BEGUN: f1=%d\n",f1);

   /* Wait for the pipe to have something to read.
   If waiting too long, close the pipe,
   or, if desired, kill the Cmd */
   while( !done ) {
      FD_ZERO(&rxset);
      //FD_SET(f1, &rxset);
      if ( f1 >= 0 )
         FD_SET(f1,&rxset); /* Check f1 */

      nfds = f1 + 1;
      tv.tv_sec = 8;
      tv.tv_usec = 500000;

      //z = select( nfds, &rxset, 0, 0, &tv );
      do {
         z = select(nfds,&rxset,0,0,&tv);
      } while ( z == -1 && errno == EINTR );

      switch (z ) {
         case 0:
            fputs(" **TIMEOUT OCCURRED**\n",stdout);
            done = 1;
            break;
         case -1:
            /* error - maybe signal is caught before
            any specified descriptors are ready */
            perror("select");
            done = 1;
            break;
         default: /* z > 0 */
            if ( f1 >= 0 && FD_ISSET(f1,&rxset) ) {
               if( fgets(buf,sizeof buf,p1) != NULL ) {
                  fputs(buf,stdout);
                  done = 0;
               }
               else if( feof(p1) ) {
                  puts("\nread EOF from f1;");
                  done = 1;
               }
               else {
                  perror("fgets");
                  done = 1;
               }
            }
            else {
               puts("FD_ISSET false\n");
            }
            break;
      } // END switch
   } // END while

   if ( pclose(p1) ) {
      perror("pclose(3)");
      return 13;
   }
   return 0;
}

Open in new window

0
phoffricCommented:
I hope this helps a little. I'll be back tonight to see if you have any questions about this. In the meantime, if you could elaborate on how you want to handle the timeout, that may improve our responses to you. I've assumed that you have no control over how the command like script behaves; that is, you have to take it as-built.

I don't know much about how much data you are expecting. If the number of lines is not deterministic, you may want to consider Data to be of a vector<string> string type to allow for growth of the array. If there is some key embedded with each line, then you may want to consider some other structure depending upon what the application is.
0
sdrussAuthor Commented:
evilrix and phoffric,

Thanks!  Guys sincerely appreciate the help.  I have implemented the "popen-select" method.  I did shift the code a bit, and now I am not really sure of the actual effect.  How can I verify the "select" call is actually performing as desired?  And, yes previously the command being invoked occasionally hung.  My command is a SNMP to query device statuses.  How can I confirm the "popen" file descriptor is being monitored?  Again, appreciate the help!   I did the following:

  if ((Data = popen(Cmd.c_str(), "r")) != NULL)
      {
            INT4 jndx = 0;

            select(nfds,&rxset,0,0,&tv);

            while (fgets(line, MAX_LINE, Data) != NULL)
           {
           }
0
phoffricCommented:
sdruss,
>> How can I verify the "select" call is actually performing as desired?
Could you list several scenarios that you would like to test, and list what the desired results of the tests should be?

I noticed that you moved the select outside of the fgets while loop. And earlier posts suggest that you expect multiple lines to be returned from the Cmd. At what points can your Cmd get hung up. And if it does get hung up, what action do you need to take?

0
sdrussAuthor Commented:
phoffric,

Yes, I have the potential for multiple lines being returned.  It appeared I was in an infinite loop when I included the select as part of the while statement.

Believe if the device is busy, the returning status can be delayed.

Previously I had:

         while (select (fdnum+1, &fds, 0, 0, &timeout) > 0)
            {
               fgets(line, MAX_LINE, Data) != NULL)

and changed to this:

         select(nfds,&rxset,0,0,&tv);

            while (fgets(line, MAX_LINE, Data) != NULL)
           {
           }



0
phoffricCommented:
Hi sdruss,
I assumed that your last post was a schematic of the changes you made. If you put the select and all its supporting code (using FD_ZERO, FD_SET, setting nfds, and tv) outside the fgets loop, then you are calling the select one time. In this case, if the Cmd does not fire up and send an initial line to the parent during the timeout period, then the output of select will be 0 indicating a timeout. If Cmd does send an initial line to the parent within the timeout period, then you don't have select being called again. So, if Cmd later stalls or gets hung up, then with your approach, since there are no more timeouts, you won't know that using this timeout approach.

Hmm, in order to know that you have a timeout, you need the return value of select. You didn't show getting the return value in your post.

You need amongst other things a return value:
         z = select(nfds,&rxset,0,0,&tv);
Then if the Cmd is initiated by the popen, but Cmd does not send a line to the parent, then z is 0. In the program post, I had:
    switch (z ) {
       case 0:
            fputs(" **TIMEOUT OCCURRED**\n",stdout);
            ...

0
phoffricCommented:
Looks like our mails crossed at the same time :)
>> It appeared I was in an infinite loop when I included the select as part of the while statement.
     Well, yes, the code I posted remains in an infinite loop as long as the child test driver program keeps sending lines to the parent in a timely manner (i.e., under 8.5 seconds between lines). If I hit Ctrl/D (i.e., EOF on the cygwin console), then the child simply exits, the pipe is torn down, and the parent gets and EOF by testing feof(p1).

     That is the intended behavior of this prototype. If you need different behavior, then we can work towards that end.
0
phoffricCommented:
see you tomorrow.
0
sdrussAuthor Commented:
phoffric

Thanks!

Suspect really need "select" call inside the while loop.  However, I need a mechanism to programatically exit the loop.  Of course using CTRL-D to terminate is not an option for me.  What condition needs to be met to exit the loop?  My desire is to exit the loop when the response to the CMD is returned, or the timer expires.  Guess I need another code snippet.  
0
phoffricCommented:
I'm back for just a little..

   Usually, between a client (in this case the parent), and the server (the CMD) there is a protocol that tells the client when the server has fulfilled the request.

   It sounds like under normal scenarios where CMD doesn't hang up, the client sends a request, and depending upon the request, the server sends back to the client one or more lines (perhaps even an indeterminate amount based upon the amount of data, in your case, perhaps the number of SNMP devices available to monitor).

   This question deals with the technical details of detecting a lapse in the CMD response (either initial response) or afterwards. To a degree, we may have offered several useful approaches.

   The only reason to put the select back in the loop is to time the interval between lines sent by CMD to its parent. If, in you experience, once CMD starts sending lines, then CMD continues faithfully to send all the remaining lines, then the select outside the loop is fine. It all depends on your functionality required and your practical experiences with the CMD hangup.

   When an abnormal situation occurs, then you may need to kill the CMD process. But I think that is another question if you need help on that. Hint, you can do a system ps | grep process-name to a file, or another popen using different file pointer; get the pid, and kill -9 the pid.
0
phoffricCommented:
>> How can I confirm the "popen" file descriptor is being monitored?

  Verifying that the popen fd works correctly is very important?

   Firstly, our little infrastructure has to be confirmed. That is, known server messages that are sent to the parent are dutifully received. How to do that? If you do not know what CMD is going to send, then create your own CMD simulator test driver. Have it respond to canned known requests and provide known responses that the parent can capture and pass onto a verifier (either automated or human). Having the parent dump out an ASCII log file of results and diffing it with the expected planned test driver results is simple enough. As far as the timeouts, have some requests include a code which tells CMD to timeout and on which line to timeout (before or after).

  Secondly, the real CMD is put back in place. Then issue a command query request manually from the command line to CMD and note results. Then immediately, issue same request programmatically from the parent.. Ideally, both are issued about the same time to get most similar results, but I'm guessing only one SNMP manager allowed at a time. What does your parent do with the lines that it receives? Does it first validate that the protocol is correct? The more error handling you have, the surer you will be that your program is doing what you intended. After validation, is there a way for the parent to know that it got good data?

  It is a little hard to look at your recent code snippets and wondering whether or not to be concerned since I don't know if you were in an infinite loop for good reasons or for buggy reasons. Without some semi-real code to build and test, it is difficult to make this determination.
0
sdrussAuthor Commented:
phoffric:

Thank-you.  This is my complete "fgets-while" loop.  Is there anyway to email you directly?
0
phoffricCommented:
fyi - My contact info is in my profile. But for the purpose of the EE knowledgebase, I think we still have to conclude our discussion here.

>> This is my complete "fgets-while" loop.
I don't see it.
0
sdrussAuthor Commented:
evilrix:
Looking for exit-loop stratedgy.  My fgets-while loop:

utility::sleep(SNMP_POPEN_WAIT);
         if ((pSnmpData = popen(snmpAgentReqCmd.c_str(), "r")) != NULL)
         {
            INT4 j = 0;

            fd_set fds;
            FD_ZERO(&fds);
            INT4 fdnum = fileno(pSnmpData);   // obtain file descriptor
            INT4 retval;
            FD_SET(fdnum, &fds);

            struct timeval timeout;
            timeout.tv_sec = 3;     // 3 seconds timeout
            timeout.tv_usec = 0;

            itsDataRecorder->RecordWrite((BYTE*) snmpAgentReqCmd.c_str(),
                             snmpAgentReqCmd.size(), DCP_TO_SNMP_DEVICE);

            // Note: Snmp Mib data output are single or multiple values
            // Waiting for the pipe to have something to read.
            // If waiting too long, (i.e. timer expires) then close pipe.

            while ((retval = select (fdnum+1, &fds, 0, 0, &timeout)) > 0)
            {  
               
               fgets(line, MAX_LINE, pSnmpData) ;
               
              //#ifdef __DEBUG__
               DcpMainLog << utility::timestamp << "snmp returns:" << string(line) << endl;
               //#endif

               // Error message reason is given in second line of
               // output
               if (j < MAX_LENGTH)
               {
                  snmpData[j++].assign(line);
               }
            }
            itsDataRecorder->RecordWrite((BYTE*) snmpData[0].c_str(),
                             snmpData[0].size(), SNMP_DEVICE_TO_DCP);
            pclose(pSnmpData);
0
phoffricCommented:
If retval is 0 (timeout; but you are not testing for that condition), and you exit the loop, then why do you do a RecordWrite. At this point isn't your SNMP agent hung up?
If so, then
1. I do not know if your RecordWrite to it will hang (is it blocking I/O waiting on a hung process?)
2. If the snmpAgentReqCmd process is hung, then the pclose(pSnmpData) will likely hang waiting for a proper termination of the child process closing is connection. Since this isn't happening, your utility::sleep method hangs forever. I mentioned that if your child process hangs, then your parent will have to kill it. By killing it, the connections will be released, and pclose() will return. (Kill it before pclose.)

I notice that you are not testing for feof as in my post. You should do that and break out of the loop if EOF is detected.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sdrussAuthor Commented:
phoffric you are great.  Thanks!
0
phoffricCommented:
I'm glad to have helped. I came in late (after you already closed this issue) and only skimmed all the other posts. But I am sure that had you followed through with the other Expert's advice using one of their approaches, you would also have come to a happy conclusion inasmuch as you were in excellent hands.

I only offered the alternate select approach because (12) years ago I found select easier to work with than dealing explicitly with a signals solution. When I had to debug signal problems, I recall having to read about all sorts of gotchas, and lots of pages to be sure that I had it right. But those Experts who are right on top of signals today wouldn't have any trouble assisting you to a good conclusion.

Also, I am using cygwin as my only near-posix platform; but I haven't tried testing signals out much, other than the timeout. I just installed it recently; so I didn't want to go down that path until I got more testing done on cygwin.

So I too am partial to select, and it's flexibility allows full-blocking, no-blocking, timeouts, and asynchronous I/O on multiple concurrent I/O file descriptors.

=========

And select is not without its own gotchas. What works in one environment may not work in another. Here is a quote from the select man page that you should be aware of:

"On Linux, select() modifies timeout to reflect the amount of time not slept; most other implementations do not do this. (POSIX.1-2001 permits either behaviour.) This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multiple select()s in a loop without reinitializing it. Consider timeout to be undefined after select() returns."
                         http://linux.die.net/man/2/select

For this reason, since I chose, in my design, to have the timeout to be constant from one line to the next, I reset the timeout variable, tv, just to be safe and portable. It may have no effect on your system, but it does not hurt; and the added benefit is that when you come back to this in a year (or in a week if something fails), you will see that you explicitly set the timeout to a known value, and that is very clear self-documenting code. Without this, you should add as comments your assumptions about what effect select has on the timeout variable.

I would also consider adding in the FD_ISSET test for added robustness and ease of maintainability.

Give a holler if you find something not working (since it may be easy to miss one test scenario in your situation).
0
HappyCactusCommented:
Select is the right approach when you have to deal with timeout with only one function.
If you have to control various levels and lines of codes, the signal (in particular SIGALRM) could be a better choice, facing the fact that in multithread application you do not have control on what thread receive the signal (you have to create a dispatcher thread and mask signals to other threads).
For a single thread, very simple problem like the initial one, I think that the two approaches are almost equivalent, select is more flexible, as you can see.
I agree with phoffric, select is indeed a good choice with complex architectures.
0
sdrussAuthor Commented:
phoffric, HappyCactus

Thanks guys for the follow-up, sincerely appreciate all the good help.

Thanks sdruss
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.