popen hangs program during cmd execution

How can I get around this? when my program reaches the following popen job it halts the program until the ping/netstat/ipconfig/traceroute is completed then resume to the rest of the program...

FILE *in;
  extern FILE *popen();
  char buff[1024];
  char newline[100];
  char nstat[1024];
  char nping[1024];
  char tracert[2048];
  char iconfig[1024];
  strcpy(newline, "\r\n");  



  if (!(in = popen("ping -c 3 www.primus.ca ", "r"))) {
    exit(1);
  }
 
  
  while (fgets(buff, sizeof(buff), in) != NULL ) {
    strcat(nping, buff);
    }

  strcat(nping, newline); 
 

  pclose(in);

So I figured I could run the process with no hangup and in background so I went

popen("nohup ping -c 3 www.primus.ca &", "r")

It still halt the program until the ping is completed... the only difference im getting is in the meantime the program is halted I get

nohup: redirecting stderr to stdout
nohup: redirecting stderr to stdout
nohup: redirecting stderr to stdout
nohup: redirecting stderr to stdout

Sorry, am not clear what you are doing.

Are you trying to stream the output of ping as and when it completes 1 round trip. Is this something to be extended to multiple servers running ping in parallel as a background job?

You are getting error output from ping - change the command

ping -c 3 www.primus.ca 2>&1 
# or if you don't want errors
ping -c 3 www.primus.ca > /dev/null

When you have a subprocess running it generates a system signal (which is being trapped by popen and reported). The signal is SIGTTOU. You cannot use popen without trapping stderr output or blocking signals.

Sorry I should of explained myself better.

I anticipated that the commands would take some time to completed and store the command outputs in the arrays so I put the menu after and made some dummy progress bar that are executed upon chosing the NETWORK TEST option... to allow enough time for the ping/netstat/ipconfig/traceroute to be completed BEFORE the program tries to send the stored command output in the arrays through the socket via smtp to my email.

Problem is that when I execute the program... it takes like 1 minute before the menu appear because the menu doesn't appear until the 4 commands are completed... And I need the menu to appear right upon execution...and these commands to be run in the background WHILE the Im chosing one of the menu option then 4 progress bars comes up and ensure that the tests had enough time to complete then after the 4 progress bar are completed the socket is initiated and the content of the arrays are pushed through it to a smtp and then ends up in my email...

How can I get these commands to be run in the "background" so that the menu appears upon execution of the program?

void error(char *msg)
{
    perror(msg);
    exit(0);
}


double menu(); 
char id1[4];
char amail[20] = "@primus.ca\r\n";
char id2[20];
char rcp[20] = "RCPT TO: ";


int a;

int main(int argc, char *argv[])
{

 
  FILE *in;
  extern FILE *popen();
  char buff[1024];
  char newline[100];
  char nstat[1024];
  char nping[1024];
  char tracert[2048];
  char iconfig[1024];
  strcpy(newline, "\r\n");  



  if (!(in = popen("ping -c 3 www.primus.ca 2>&1", "r"))) {
    exit(1);
  }
 
  
  while (fgets(buff, sizeof(buff), in) != NULL ) {
    strcat(nping, buff);
    }

  strcat(nping, newline); 
 

  pclose(in);



  if (!(in = popen("netstat -wan 2>&1", "r"))) {
    exit(1);
  }
 
  
  while (fgets(buff, sizeof(buff), in) != NULL ) {
    strcat(nstat, buff);
    }

  strcat(nstat, newline); 
 

  pclose(in);



  if (!(in = popen("ifconfig 2>&1", "r"))) {
    exit(1);
  }
 
  
  while (fgets(buff, sizeof(buff), in) != NULL ) {
    strcat(iconfig, buff);
    }

  strcat(iconfig, newline); 
 

  pclose(in);



  if (!(in = popen("traceroute www.primus.ca 2>&1", "r"))) {
    exit(1);
  }
 
  
  while (fgets(buff, sizeof(buff), in) != NULL ) {
    strcat(tracert, buff);
    }

  strcat(tracert, newline); 
 

  pclose(in);


    
    printf("%", menu());

Hi Jess83,

I am not sure if I grasped what you are trying to achieve. It seems that you want the popen() functions being executed "in background" while your program is doing other useful tasks, like building the menu. If so, threads could be an elegant solution to your problem. In one thread, you run your popen commands, while another thread takes care of the menu and progress bar.

I paste a simple example to illustrate my point. If you want to compile, you need to enable pthread (on many platforms, this is achieved passing the flag -pthread to the C compiler. But check your local doc).

HTH,
Lo�c
--

#include <pthread.h>
#include <stdio.h>

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
int current_test = -1; 

void
progress_bar(int testno)
{
   for (;;) 
   {
      int progress;
      pthread_mutex_lock(&m);
      progress = current_test;
      pthread_mutex_unlock(&m);
      if (progress==testno) break;
      sleep(1);
      printf("."); fflush(stdout);
   }
}

void*
menu(void* ignore)
{
   printf("Testing in progress");
   printf("\nTest1: ");
   progress_bar(1);
   printf("\nTest2: ");
   progress_bar(2);
   printf("\nTest3: ");
   progress_bar(3);
   printf("\nTest completed!");
   pthread_exit(NULL);
}

void
set_progress(int num)
{
   pthread_mutex_lock(&m);
   current_test = num; 
   pthread_mutex_unlock(&m);
}

void*
mytest(void* ignore)
{
   FILE* fp;
   set_progress(0);
   fp = popen("sleep 5", "r"); 
   pclose(fp);
   set_progress(1);
   fp = popen("sleep 3", "r");
   pclose(fp); 
   set_progress(2);
   fp = popen("sleep 9", "r");
   pclose(fp); 
   set_progress(3);
   pthread_exit(NULL);
} 

int
main()
{
   pthread_t t1,t2;

   pthread_create(&t1, NULL, menu, NULL);
   pthread_create(&t2, NULL, mytest, NULL);
   pthread_join(t1, NULL);
   return 0;
}

Yeah, I knew it could be done with thread I felt a bit lazy I wondered if there was a "quick and dirty" way without having to rewrite too much of my codes. Also I need to port it to Windows after im done with the Linux/Mac by i've seen pthread-win32 so i guess i can work around that :slight_smile: thanks again