示例#1
0
static int pipelineExecProc(struct pipeline* pl, struct plProc *proc,
                            int prevStdoutFd, int stdinFd, int stdoutFd, int stderrFd,
                            void *otherEndBuf, size_t otherEndBufSize)
/* start a process in the pipeline, return the stdout fd of the process */
{
/* determine stdin/stdout to use */
int procStdinFd, procStdoutFd;
if (proc == pl->procs)
    procStdinFd = stdinFd; /* first process in pipeline */
else
    procStdinFd = prevStdoutFd;
if (proc->next == NULL)
    procStdoutFd = stdoutFd; /* last process in pipeline */
else
    prevStdoutFd = pipeCreate(&procStdoutFd);

/* start process */
if ((proc->pid = fork()) < 0)
    errnoAbort("can't fork");
if (proc->pid == 0)
    {
    if (otherEndBuf != NULL)
        plProcMemWrite(proc, procStdoutFd, stderrFd, otherEndBuf, otherEndBufSize);
    else
        plProcExecChild(proc, procStdinFd, procStdoutFd, stderrFd);
    }

/* don't leave intermediate pipes open in parent */
if (proc != pl->procs)
    safeClose(&procStdinFd);
if (proc->next != NULL)
    safeClose(&procStdoutFd);
return prevStdoutFd;
}
示例#2
0
/* Closes all open FDs except for stdin, stdout and stderr */
static void
closeFDs(int errnofd) {
    DIR *dp;
    int dfd;
    struct dirent *ep;
    int fdNum = -1;

    dfd = open("/proc/self/fd/", O_RDONLY);
    dp = fdopendir(dfd);
    while ((ep = readdir(dp))) {
        if(sscanf(ep->d_name, "%d", &fdNum) < 1) {
            continue;
        }

        if (fdNum < 3) {
            continue;
        }

        if (fdNum == dfd) {
            continue;
        }

        if (fdNum == errnofd) {
            continue;
        }

        safeClose(fdNum);
    }

    closedir(dp);
    safeClose(dfd);
}
示例#3
0
int
main(int argc, char *argv[]) {
  int fd, newfd;
  int numWritten;
  Bool useDup2;

  if (argc < 2 || argc > 3) {
    helpAndLeave(argv[0], EXIT_FAILURE);
  }

  fd = (int) atol(argv[1]);
  newfd = -1; /* if not using dup2, this variable will not be used */

  if (argc == 3) {
    useDup2 = TRUE;
    newfd = (int) atol(argv[2]);
  } else {
    useDup2 = FALSE;
  }

  newfd = duplicate(fd, newfd, useDup2);

  numWritten = write(newfd, writeStr, sizeof(writeStr));
  if (numWritten == -1) {
    pexit("write");
  }

  safeClose(fd);
  safeClose(newfd);

  printf("Done. Written %d bytes to the new file descriptor #%d\n", numWritten, newfd);

  return EXIT_SUCCESS;
}
示例#4
0
static void pipelineStartWrite(struct pipeline *pl, int stdoutFd, int stderrFd)
/* start a write pipeline */
{
int pipeRdFd = pipeCreate(&pl->pipeFd);
pipelineExec(pl, pipeRdFd, stdoutFd, stderrFd, NULL, 0);
safeClose(&pipeRdFd);
}
示例#5
0
int
_dup2(int oldfd, int newfd) {
  int nextfd;

  /* First, check if oldfd is a valid file descriptor */
  int flags = fcntl(oldfd, F_GETFL);
  if (flags == -1) {
    errno = EBADF;
    return -1;
  }

  /* if both descriptors are the same, do nothing */
  if (oldfd == newfd) {
    return newfd;
  }

  /* close newfd if necessary */
  flags = fcntl(newfd, F_GETFL);
  if (flags != -1) {
    safeClose(newfd);
  }

  /* perform the copy */
  nextfd = fcntl(oldfd, F_DUPFD, newfd);

  if (nextfd != newfd) {
    fprintf(stderr, "_dup2 is not atomic, so sometimes it fails. It just did. Expected fd %d, got %d\n", newfd, nextfd);
    exit(EXIT_FAILURE);
  }

  return newfd;
}
 void closeAll(poll_list::iterator begin, poll_list::iterator end)
 {
   while (begin != end)
   {
     safeClose(begin->fd);
     ++begin;
   }
 }
示例#7
0
static void pipelineStartRead(struct pipeline *pl, int stdinFd, int stderrFd,
                              void *otherEndBuf, size_t otherEndBufSize)
/* start a read pipeline */
{
int pipeWrFd;
pl->pipeFd = pipeCreate(&pipeWrFd);
pipelineExec(pl, stdinFd, pipeWrFd, stderrFd, otherEndBuf, otherEndBufSize);
safeClose(&pipeWrFd);
}
示例#8
0
struct pipeline *pipelineOpen(char ***cmds, unsigned opts,
                              char *otherEndFile, char *stderrFile)
/* Create a pipeline from an array of commands.  See pipeline.h for
 * full documentation */
{
int otherEndFd;
int stderrFd = (stderrFile == NULL) ? STDERR_FILENO : openWrite(stderrFile);

checkOpts(opts);
if (opts & pipelineRead)
    otherEndFd = (otherEndFile == NULL) ? STDIN_FILENO : openRead(otherEndFile);
else
    otherEndFd = (otherEndFile == NULL) ? STDOUT_FILENO : openWrite(otherEndFile);
struct pipeline *pl = pipelineOpenFd(cmds, opts, otherEndFd, stderrFd);
safeClose(&otherEndFd);
if (stderrFile != NULL)
    safeClose(&stderrFd);
return pl;
}
示例#9
0
/**
 * Safely connect socket file descriptor to server address. 
 * @see man(2) connect for params
 ******************************************************************************/
void safeConnect( int sockfd, const struct sockaddr *addr,
		 socklen_t addrlen)
{
  errno = 0;
  if (connect( sockfd, addr, addrlen ) < 0 ) {
    perror("connect error"); 
    safeClose(sockfd);
    exit(1);
  }
}
示例#10
0
/**
 * Safely bind an address to a socked file descriptor.
 * @param socket created by socket()
 * @param address pointer to sockaddr struct describing the server
 * @see man(2) bind for wrapped function description.
 ******************************************************************************/
void safeBind(int socket, const struct sockaddr *address,
     socklen_t address_len)
{
  errno = 0;
  if ( bind(socket, address, address_len) < -1) {
    perror("bind error"); 
    safeClose(socket);
    exit(1);
  }
}
示例#11
0
Hardware::~Hardware() {
	safeClose();

	//delete buzz;
	delete adc_i2c;
	delete adc;
	delete imu;
	delete pwmR;
	delete pwmG;
	delete pwmB;
}
示例#12
0
void ProgramRunner::operator()() {
    // Send the never_close_handle flag so that we can handle closing the fd below with safeClose.
    boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> fdBuf(
        _pipe, boost::iostreams::file_descriptor_flags::never_close_handle);
    std::istream fdStream(&fdBuf);

    std::string line;
    while (std::getline(fdStream, line)) {
        if (line.find('\0') != std::string::npos) {
            programOutputLogger.appendLine(
                _port, _pid, _name, "WARNING: mongod wrote null bytes to output");
        }
        programOutputLogger.appendLine(_port, _pid, _name, line);
    }

    // Close the read end of the pipe.
    safeClose(_pipe);
}
示例#13
0
void gracefullyExit(int fd,struct sigaction signal){
	restoreHandler(signal);
	safeUnlink();
	safeClose(fd);

}
示例#14
0
extern "C" JNIEXPORT void JNICALL 
Java_java_lang_Runtime_exec(JNIEnv* e, jclass, 
                            jobjectArray command, jlongArray process)
{
  char** argv = static_cast<char**>
    (malloc((e->GetArrayLength(command) + 1) * sizeof(char*)));
  int i;
  for(i = 0; i < e->GetArrayLength(command); i++){
    jstring element = (jstring) e->GetObjectArrayElement(command, i);
    char* s = const_cast<char*>(e->GetStringUTFChars(element, 0));
    argv[i] = s;
  }
  argv[i] = 0;
  
  int in[] = { -1, -1 };
  int out[] = { -1, -1 };
  int err[] = { -1, -1 };
  int msg[] = { -1, -1 };
  
  makePipe(e, in);
  if(e->ExceptionCheck()) return;
  jlong inDescriptor = static_cast<jlong>(in[0]);
  e->SetLongArrayRegion(process, 2, 1, &inDescriptor);
  makePipe(e, out);
  if(e->ExceptionCheck()) return;
  jlong outDescriptor = static_cast<jlong>(out[1]);
  e->SetLongArrayRegion(process, 3, 1, &outDescriptor);
  makePipe(e, err);
  if(e->ExceptionCheck()) return;
  jlong errDescriptor = static_cast<jlong>(err[0]);
  e->SetLongArrayRegion(process, 4, 1, &errDescriptor);
  makePipe(e, msg);
  if(e->ExceptionCheck()) return;
  if(fcntl(msg[1], F_SETFD, FD_CLOEXEC) != 0) {
    throwNewErrno(e, "java/io/IOException");
    return;
  }
  
#ifdef __QNX__
  // fork(2) doesn't work in multithreaded QNX programs.  See
  // http://www.qnx.com/developers/docs/6.4.1/neutrino/getting_started/s1_procs.html
  pid_t pid = vfork();
#else
  // We might be able to just use vfork on all UNIX-style systems, but
  // the manual makes it sound dangerous due to the shared
  // parent/child address space, so we use fork if we can.
  pid_t pid = fork();
#endif
  switch(pid){
  case -1: // error
    throwNewErrno(e, "java/io/IOException");
    return;
  case 0: { // child
    // Setup stdin, stdout and stderr
    dup2(in[1], 1);
    close(in);
    dup2(out[0], 0);
    close(out);
    dup2(err[1], 2);
    close(err);
    close(msg[0]);
    
    execvp(argv[0], argv);
    
    // Error if here
    int val = errno;
    ssize_t rv UNUSED = write(msg[1], &val, sizeof(val));
    exit(127);
  } break;
    
  default: { //parent
    jlong JNIPid = static_cast<jlong>(pid);
    e->SetLongArrayRegion(process, 0, 1, &JNIPid);
    
    safeClose(in[1]);
    safeClose(out[0]);
    safeClose(err[1]);
    safeClose(msg[1]);
      
    int val;
    int r = read(msg[0], &val, sizeof(val));
    if(r == -1) {
      throwNewErrno(e, "java/io/IOException");
      return;
    } else if(r) {
      errno = val;
      throwNewErrno(e, "java/io/IOException");
      return;
    }
  } break;
  }
  
  safeClose(msg[0]);
  clean(e, command, argv);
  
  fcntl(in[0], F_SETFD, FD_CLOEXEC);
  fcntl(out[1], F_SETFD, FD_CLOEXEC);
  fcntl(err[0], F_SETFD, FD_CLOEXEC);
}
示例#15
0
/* Python's implementation of Popen forks back to python before execing.
 * Forking a python proc is a very complex and volatile process.
 *
 * This is a simpler method of execing that doesn't go back to python after
 * forking. This allows for faster safer exec.
 *
 * return NULL on error and sets the python error accordingly.
 */
static PyObject *
createProcess(PyObject *self, PyObject *args)
{
    int cpid;
    int deathSignal = 0;
    int rv;

    int outfd[2] = {-1, -1};
    int in1fd[2] = {-1, -1};
    int in2fd[2] = {-1, -1};

    int errnofd[2] = {-1, -1};
    int childErrno = 0;

    PyObject* pyArgList;
    PyObject* pyEnvList;
    const char* cwd;
    int close_fds = 0;

    char** argv = NULL;
    char** envp = NULL;

    if (!PyArg_ParseTuple(args, "O!iiiiiiizOi:createProcess;",
                &PyList_Type, &pyArgList, &close_fds,
                &outfd[0], &outfd[1],
                &in1fd[0], &in1fd[1],
                &in2fd[0], &in2fd[1],
                &cwd, &pyEnvList, &deathSignal)) {
        return NULL;
    }

    argv = pyListToArray(pyArgList, 1);
    if (!argv) {
        goto fail;
    }

    if (PyList_Check(pyEnvList)) {
        envp = pyListToArray(pyEnvList, 0);
        if (!envp) {
            goto fail;
        }
    }

    if(pipe(errnofd) < 0) {
        PyErr_SetFromErrno(PyExc_OSError);
        goto fail;
    }

try_fork:
    cpid = fork();
    if (cpid < 0) {
        if (errno == EAGAIN ||
            errno == EINTR ) {
            goto try_fork;
        }

        PyErr_SetFromErrno(PyExc_OSError);
        goto fail;
    }

    if (!cpid) {
        safeClose(0);
        safeClose(1);
        safeClose(2);

        dup2(outfd[0], 0);
        dup2(in1fd[1], 1);
        dup2(in2fd[1], 2);

        safeClose(outfd[0]);
        safeClose(outfd[1]);
        safeClose(in1fd[0]);
        safeClose(in1fd[1]);
        safeClose(in2fd[0]);
        safeClose(in2fd[1]);
        safeClose(errnofd[0]);

        if (deathSignal) {
            childErrno = prctl(PR_SET_PDEATHSIG, deathSignal);
            if (childErrno < 0) {
                childErrno = errno;
            }
            /* Check that parent did not already die between fork and us
             * setting the death signal */
            if (write(errnofd[1], &childErrno, sizeof(int)) < sizeof(int)) {
                exit(-1);
            }

            if (childErrno != 0) {
                exit(-1);
            }
        }

        if (setCloseOnExec(errnofd[1]) < 0) {
            goto sendErrno;
        }

        if (close_fds) {
            closeFDs(errnofd[1]);
        }

        if (cwd) {
            if (chdir(cwd) < 0) {
                goto sendErrno;
            }
            setenv("PWD", cwd, 1);
        }
exec:
        if (envp) {
            execvpe(argv[0], argv, envp);
        } else {
            execvp(argv[0], argv);
        }

        if (errno == EINTR ||
            errno == EAGAIN )
        {
            goto exec;
        }
sendErrno:
        if (write(errnofd[1], &errno, sizeof(int)) < 0) {
            exit(errno);
        }
        exit(-1);
    }

    safeClose(errnofd[1]);
    errnofd[1] = -1;

    if (deathSignal) {
        /* death signal sync point */
        rv = safeRead(errnofd[0], &childErrno, sizeof(int));
        if (rv != sizeof(int)) {
            PyErr_SetFromErrno(PyExc_OSError);
            goto fail;
        } else if (childErrno != 0) {
            PyErr_SetString(PyExc_OSError, strerror(childErrno));
            goto fail;
        }
    }

    /* error sync point */
    rv = safeRead(errnofd[0], &childErrno, sizeof(int));
    if (rv == sizeof(int)) {
        PyErr_SetString(PyExc_OSError, strerror(childErrno));
        goto fail;
    } else if (rv < 0) {
        PyErr_SetFromErrno(PyExc_OSError);
        goto fail;
    }

    safeClose(errnofd[0]);
    errnofd[0] = -1;

    /* From this point errors shouldn't occur, if they do something is very
     * very very wrong */

    freeStringArray(argv);

    if (envp) {
        freeStringArray(envp);
    }

    return Py_BuildValue("(iiii)", cpid, outfd[1], in1fd[0], in2fd[0]);

fail:
    if (argv) {
        freeStringArray(argv);
    }

    if (envp) {
        freeStringArray(envp);
    }

    if (errnofd[0] >= 0) {
        safeClose(errnofd[0]);
    }

    if (errnofd[1] >= 0) {
        safeClose(errnofd[1]);
    }

    return NULL;
}
示例#16
0
void ProgramRunner::start() {
    int pipeEnds[2];

    {
        // NOTE(JCAREY):
        //
        // We take this lock from before our call to pipe until after we close the write side (in
        // the parent) to avoid leaking fds from threads racing around fork().  I.e.
        //
        // Thread A: calls pipe()
        // Thread B: calls fork()
        // A: sets cloexec on read and write sides
        // B: has a forked child with open fds
        // A: spawns a child thread to read it's child process's stdout
        // A: A's child process exits
        // A: wait's on A's reader thread in de-register
        // A: deadlocks forever (because the child reader thread stays in read() because of the open
        //    fd in B)
        //
        // Holding the lock for the duration of those events prevents the leaks and thus the
        // associated deadlocks.
        stdx::lock_guard<stdx::mutex> lk(_createProcessMtx);
        int status = pipe(pipeEnds);
        if (status != 0) {
            const auto ewd = errnoWithDescription();
            error() << "failed to create pipe: " << ewd;
            fassertFailed(16701);
        }
#ifndef _WIN32
        // The calls to fcntl to set CLOEXEC ensure that processes started by the process we are
        // about to fork do *not* inherit the file descriptors for the pipe. If grandchild processes
        // could inherit the FD for the pipe, than the pipe wouldn't close on child process exit. On
        // windows, instead the handle inherit flag is turned off after the call to CreateProcess.
        status = fcntl(pipeEnds[0], F_SETFD, FD_CLOEXEC);
        if (status != 0) {
            const auto ewd = errnoWithDescription();
            error() << "failed to set FD_CLOEXEC on pipe end 0: " << ewd;
            fassertFailed(40308);
        }
        status = fcntl(pipeEnds[1], F_SETFD, FD_CLOEXEC);
        if (status != 0) {
            const auto ewd = errnoWithDescription();
            error() << "failed to set FD_CLOEXEC on pipe end 1: " << ewd;
            fassertFailed(40317);
        }
#endif

        fflush(0);

        launchProcess(pipeEnds[1]);  // sets _pid

        // Close the write end of the pipe.
        safeClose(pipeEnds[1]);
    }

    if (_port >= 0) {
        registry.registerProgram(_pid, _port);
    } else {
        registry.registerProgram(_pid);
    }

    _pipe = pipeEnds[0];

    {
        stringstream ss;
        ss << "shell: started program (sh" << _pid << "): ";
        for (unsigned i = 0; i < _argv.size(); i++) {
            ss << " " << _argv[i];
        }
        log() << ss.str();
    }
}