From c15f544356dfebf6d08887e73fa156d4e70e2bbc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 20 Jul 2006 12:17:25 +0000 Subject: * Call find-runtime-roots.pl from the garbage collector to prevent running applications etc. from being garbage collected. --- src/libutil/util.cc | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'src/libutil/util.cc') diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 9e3e0bae20df..a8ad3fe4807b 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -13,6 +13,10 @@ #include #include +#ifdef __CYGWIN__ +#include +#endif + #include "util.hh" @@ -434,6 +438,23 @@ void writeFull(int fd, const unsigned char * buf, size_t count) } +string drainFD(int fd) +{ + string result; + unsigned char buffer[4096]; + while (1) { + ssize_t rd = read(fd, buffer, sizeof buffer); + if (rd == -1) { + if (errno != EINTR) + throw SysError("reading from file"); + } + else if (rd == 0) break; + else result.append((char *) buffer, rd); + } + return result; +} + + ////////////////////////////////////////////////////////////////////// @@ -643,6 +664,69 @@ void Pid::setSeparatePG(bool separatePG) +////////////////////////////////////////////////////////////////////// + + +string runProgram(Path program) +{ + /* Create a pipe. */ + Pipe pipe; + pipe.create(); + + /* Fork. */ + Pid pid; + pid = fork(); + switch (pid) { + + case -1: + throw SysError("unable to fork"); + + case 0: /* child */ + try { + pipe.readSide.close(); + + if (dup2(pipe.writeSide, STDOUT_FILENO) == -1) + throw SysError("dupping from-hook write side"); + + execl(program.c_str(), program.c_str(), (char *) 0); + throw SysError(format("executing `%1%'") % program); + + } catch (exception & e) { + cerr << "error: " << e.what() << endl; + } + quickExit(1); + } + + /* Parent. */ + + pipe.writeSide.close(); + + string result = drainFD(pipe.readSide); + + /* Wait for the child to finish. */ + int status = pid.wait(true); + if (!statusOk(status)) + throw Error(format("program `%1% %2%") + % program % statusToString(status)); + + return result; +} + + +void quickExit(int status) +{ +#ifdef __CYGWIN__ + /* Hack for Cygwin: _exit() doesn't seem to work quite right, + since some Berkeley DB code appears to be called when a child + exits through _exit() (e.g., because execve() failed). So call + the Windows API directly. */ + ExitProcess(status); +#else + _exit(status); +#endif +} + + ////////////////////////////////////////////////////////////////////// -- cgit 1.4.1