Changeset - d18bf2f45283
[Not reviewed]
default
0 1 0
Nathan Brink (binki) - 15 years ago 2010-09-03 00:08:20
ohnobinki@ohnopublishing.net
execio: Remove some debug messages.
1 file changed with 3 insertions and 7 deletions:
0 comments (0 inline, 0 general)
src/common/execio.c
Show inline comments
 
@@ -88,176 +88,172 @@ int execio_open(struct execio **rem, con
 
	  /* the waitpid(2) seems to indicate that only when the child is terminated will this wait return. */
 
	  waitpid(child, &childstatus, 0); 
 
	}
 
      (*rem)->pipe_write = pipe_write[1];
 
      (*rem)->pipe_read = pipe_read[0];
 
      (*rem)->state = 0;
 
      (*rem)->child = child;
 
      
 
      return 0;
 
    }
 
  
 
  /* child */
 
  else
 
    {
 
      /* close unused pipes */
 
      close(pipe_write[1]);
 
      close(pipe_read[0]);
 

	
 
      /*
 
	reset stdin, stdout, and stderr to the appropriate files. OK, not stderr :-) 
 
      */
 
      dup2(pipe_read[1], STDOUT_FILENO);
 
      dup2(pipe_write[0], STDIN_FILENO);
 
      /*
 
	close the fds that were dup'd
 
       */
 
      close(pipe_read[1]);
 
      close(pipe_write[0]);
 

	
 
      /* 
 
	 close all other file descriptors. We want to keep 0, 1, and 2 open. We don't know that the last open() or pipe() always gives the highest fd number. However, I will assume that it does. Maybe this is a bad idea:
 
       */
 
      counter = pipe_write[0];
 
      if(counter < pipe_write[1])
 
	counter = pipe_write[1];
 
      if(counter < pipe_read[0])
 
	counter = pipe_read[0];
 
      if(counter < pipe_read[1])
 
	counter = pipe_read[1];
 
      counter2 = 0;
 
      maxfds = counter;
 
      while(counter > 2)
 
	{
 
	  if(!close(counter))
 
	    counter2 ++; /* record how many descriptors we still had open :-) */
 
	  counter --;
 
	}
 
      
 
      /* stderr is the only stream we haven't confiscated atm - just for fun - I will confiscate it later, though, to support parsing error messages */
 
      fprintf(stderr, "closed %d/%d fds before execing \"%s\"\n", counter2, maxfds, progname);
 

	
 
      /*
 
	now exec: execvp uses interpreter to find the file to exec
 
       */
 
      execvp(progname, argv);
 

	
 
      fprintf(stderr, "uh-oh, ``%s'' didn't start for execio\n", progname);
 
      exit(1);
 
    }
 
}
 

	
 
/*
 
  returns 1 if child has exited, 
 
  returns 0 if child is still alive
 
 */
 
int _execio_checkpid(struct execio *eio)
 
{
 
  int childstatus;
 
  
 
#ifdef _WIN32
 
  waitpid(eio->child, &childstatus, 0);
 
#else
 
  waitpid(eio->child, &childstatus, WNOHANG);
 
#endif
 
  /* perror()? */
 

	
 
  return WIFEXITED(childstatus);
 
}
 

	
 

	
 
int execio_read(struct execio *eio, const void *buf, size_t len, size_t *bytesread)
 
{
 
  ssize_t ret;
 
  /*
 
    TODO: detect NULL eio? 
 
    TODO: errno?
 
    update status of eio for execio_status/to be able to cleanup subproc??
 

	
 
    whenever read() returns 0, it means EOF
 
   */
 
  
 
  ret = read(eio->pipe_read, buf, len);
 
  if(ret == -1)
 
    {
 
      (*bytesread) = 0;
 
      perror("read");
 
      switch(errno)
 
	{
 
	case EAGAIN:
 
	case EINTR:
 
	  return 0;
 
	  break;
 
	default:
 
	  return 1;
 
	}
 
    }
 

	
 
  (*bytesread) = (size_t)ret;
 
  if(!ret)
 
    {
 
      /* should also be able to figure out if is bad fd and should set EXECIO_STATE_ERROR instead of _EOF */
 
      eio->state = EXECIO_STATE_EOF;
 
      return 1;
 
    }
 

	
 
  return 0;
 
}
 

	
 
int execio_write(struct execio *eio, const void *buf, size_t len, size_t *bytesread)
 
{
 
  errno = 0;
 
  (*bytesread) = write(eio->pipe_write, buf, len);
 
  if(!*bytesread)
 
    {
 
      switch(errno)
 
	{
 
	case EPIPE:
 
	  /* 
 
	     the program closed the pipe (died)
 
	  */
 
	fprintf(stderr, "execio_write: the child program closed its stdin pipe\n");
 
	eio->state = EXECIO_STATE_EOF;
 
	break;
 
	  fprintf(stderr, "execio_write: the child program closed its stdin pipe\n");
 
	  eio->state = EXECIO_STATE_EOF;
 
	  break;
 
	
 
	default:
 
	  fprintf(stderr, "execio_write: unhandled error writing to an fd: \n");
 
	  perror("write");
 
	  eio->state = EXECIO_STATE_ERROR;
 
	  break;
 
	  
 
	}
 
      
 
      return 1;
 
    }
 

	
 
  return 0;
 
}
 

	
 

	
 
enum execio_state execio_state(struct execio *eio)
 
{
 
  return eio->state;
 
}
 

	
 

	
 
int execio_close(struct execio *eio)
 
{
 
  int childstatus;
 

	
 
  close(eio->pipe_read);
 
  close(eio->pipe_write);
 

	
 
  /* maybe we should just kill rather than term the child */
 
  kill(eio->child, SIGTERM);
 
  /* 
 
     the waitpid(2) seems to indicate that only when the child is terminated will this wait return. 
 
     This are of code will probably need improving - the ability to seng SIGKILL after a timeout? So we'll output a debug line before running waitpid
 
  */
 
  fprintf(stderr, "execio_close: running waitpid\n");
 
  waitpid(eio->child, &childstatus, 0);
 

	
 
  free(eio);
 
  
 
  return 0;
 
}
 

	
0 comments (0 inline, 0 general)