guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

319/376: Use posix_spawn to run the pager


From: Ludovic Courtès
Subject: 319/376: Use posix_spawn to run the pager
Date: Wed, 28 Jan 2015 22:05:53 +0000

civodul pushed a commit to tag 1.8
in repository guix.

commit d34d2b2bbf784c0bb420a50905af25e02c6e4989
Author: Eelco Dolstra <address@hidden>
Date:   Fri Dec 5 20:34:41 2014 +0100

    Use posix_spawn to run the pager
    
    In low memory environments, "nix-env -qa" failed because the fork to
    run the pager hit the kernel's overcommit limits. Using posix_spawn
    gets around this. (Actually, you have to use posix_spawn with the
    undocumented POSIX_SPAWN_USEVFORK flag, otherwise it just uses
    fork/exec...)
---
 src/libmain/shared.cc |   38 ++++++++++++++++++++++++++++++--------
 src/libutil/types.hh  |    1 +
 src/libutil/util.cc   |   10 ++++++++--
 3 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index c4b5c21..d0c75a8 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -15,6 +15,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <signal.h>
+#include <spawn.h>
 
 
 namespace nix {
@@ -305,14 +306,35 @@ RunPager::RunPager()
     Pipe toPager;
     toPager.create();
 
-    pid = startProcess([&]() {
-        if (dup2(toPager.readSide, STDIN_FILENO) == -1)
-            throw SysError("dupping stdin");
-        if (!getenv("LESS"))
-            setenv("LESS", "FRSXMK", 1);
-        execl("/bin/sh", "sh", "-c", pager.c_str(), NULL);
-        throw SysError(format("executing ‘%1%’") % pager);
-    });
+    // FIXME: should do this in the child environment.
+    if (!getenv("LESS"))
+        setenv("LESS", "FRSXMK", 1);
+
+    /* Start the pager using posix_spawn. */
+    pid_t pid_;
+    const char * argv[] = { "sh", "-c", pager.c_str(), 0 };
+
+    posix_spawn_file_actions_t fileActions;
+    int err = posix_spawn_file_actions_init(&fileActions);
+    if (err) throw SysError(err, "creating POSIX file actions");
+    err = posix_spawn_file_actions_adddup2(&fileActions, toPager.readSide, 
STDIN_FILENO);
+    if (err) throw SysError(err, "adding to POSIX file actions");
+
+    posix_spawnattr_t spawnAttrs;
+    err = posix_spawnattr_init(&spawnAttrs);
+    if (err) throw SysError(err, "creating POSIX spawn attrs");
+#ifdef POSIX_SPAWN_USEVFORK
+    err = posix_spawnattr_setflags(&spawnAttrs, POSIX_SPAWN_USEVFORK);
+    if (err) throw SysError(err, "setting POSIX spawn attr flag");
+#endif
+
+    err = posix_spawn(&pid_, "/bin/sh", &fileActions, &spawnAttrs, (char * 
const *) argv, environ);
+
+    posix_spawn_file_actions_destroy(&fileActions);
+    posix_spawnattr_destroy(&spawnAttrs);
+
+    if (err) throw SysError(err, format("running ‘%1%’") % pager);
+    pid = pid_;
 
     if (dup2(toPager.writeSide, STDOUT_FILENO) == -1)
         throw SysError("dupping stdout");
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 160884e..030996a 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -73,6 +73,7 @@ class SysError : public Error
 public:
     int errNo;
     SysError(const FormatOrString & fs);
+    SysError(int errNo, const FormatOrString & fs);
 };
 
 
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 305e470..60be02c 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -45,8 +45,14 @@ BaseError & BaseError::addPrefix(const FormatOrString & fs)
 
 
 SysError::SysError(const FormatOrString & fs)
-    : Error(format("%1%: %2%") % fs.s % strerror(errno))
-    , errNo(errno)
+    : SysError(errno, fs)
+{
+}
+
+
+SysError::SysError(int errNo, const FormatOrString & fs)
+    : Error(format("%1%: %2%") % fs.s % strerror(errNo))
+    , errNo(errNo)
 {
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]