Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return status of execve

Tags:

c

process

exec

I want to send exit status 0 from the execve process to the process which started it. Because on Success execve never returns, So I am not able to do anything after that. But I want if execve ran successful.

like image 504
Rohit Jindal Avatar asked Mar 19 '13 10:03

Rohit Jindal


2 Answers

You can verify that exec succeeded using FD_CLOEXEC:

  • create a pipe.

  • fork.

  • in the child, close the read end of the pipe and set the FD_CLOEXEC flag on the write end of the pipe. Then proceed with exec. If exec succeeds, the pipe will be automatically closed due to FD_CLOEXEC. If exec fails, write a byte to the pipe and exit.

  • in the parent, close the write end of the pipe and read from the read end. If you read 0 bytes (EOF), it means that exec succeeded. If you read a byte in the pipe, it means that exec failed.

The data written over the pipe in case of failure can be used to transmit error information, such as value of errno after exec.

The code, with error checking omitted for brevity, would look like this:

int pipe_fds[2];
pipe(pipe_fds);
if (!fork()) {
  close(pipe_fds[0]);
  fcntl(pipe_fds[1], F_SETFD, F_CLOEXEC);
  execve(...);
  write(pipe_fds[1], "", 1);
  _exit(1);
}
else {
  int n;
  char out;
  close(pipe_fds[1]);
  n = read(pipe_fds[0], &out, 1);
  if (n == 0)
    printf("exec successful\n");
  else
    printf("exec failed\n");
  close(pipe_fds[0]);
}

Note that this technique can be unsafe if other threads may exec their own processes in parallel. The issue is that there is a delay between when the pipe is created and when the close-on-exec flag gets set. If an unrelated thread forks and execs during that critical window, the child will inherit pipe_fds[1] and won't close it, causing the parent to hang. This can be fixed using the Linux-specific pipe2 call which allows atomically creating the pipe with the close-on-exec flag set.

like image 115
user4815162342 Avatar answered Oct 16 '22 15:10

user4815162342


to wait you process launched by fork() finish, you can use wait():

/* parent */
int status;
while (wait(&status) != uproc.pid) {
    printf("waiting for child to exit");
    }

and based on this question

The exit status of the child is provided by the wait function, in the status variable.

You get the exit status by using the WEXITSTATUS macro, but only if the program exited normally (i.e. called exit or returned from its main function):

if (WIFEXITED(status))
    printf("Child exit status: %d\n", WEXITSTATUS(status));
else
    printf("Child exited abnormally\n");
like image 2
MOHAMED Avatar answered Oct 16 '22 13:10

MOHAMED