aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/eval.cc2
-rw-r--r--src/libexpr/nixexpr.cc4
-rw-r--r--src/libexpr/parser.cc2
-rw-r--r--src/libmain/shared.cc15
-rw-r--r--src/libstore/db.cc9
-rw-r--r--src/libstore/exec.cc4
-rw-r--r--src/libstore/normalise.cc6
-rw-r--r--src/libstore/pathlocks.cc7
-rw-r--r--src/libstore/references.cc3
-rw-r--r--src/libstore/store.cc2
-rw-r--r--src/libutil/archive.cc6
-rw-r--r--src/libutil/util.cc17
-rw-r--r--src/libutil/util.hh13
13 files changed, 86 insertions, 4 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index f6634e892..0470deee9 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -227,6 +227,8 @@ Expr evalExpr2(EvalState & state, Expr e)
Expr evalExpr(EvalState & state, Expr e)
{
+ checkInterrupt();
+
startNest(nest, lvlVomit,
format("evaluating expression: %1%") % e);
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 816b39dc1..dd0f5d58a 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -87,6 +87,8 @@ string aterm2String(ATerm t)
ATerm bottomupRewrite(TermFun & f, ATerm e)
{
+ checkInterrupt();
+
if (ATgetType(e) == AT_APPL) {
AFun fun = ATgetAFun(e);
int arity = ATgetArity(fun);
@@ -149,6 +151,8 @@ Expr makeAttrs(const ATermMap & attrs)
Expr substitute(const ATermMap & subs, Expr e)
{
+ checkInterrupt();
+
ATMatcher m;
string s;
diff --git a/src/libexpr/parser.cc b/src/libexpr/parser.cc
index b9e79e13d..83b656342 100644
--- a/src/libexpr/parser.cc
+++ b/src/libexpr/parser.cc
@@ -26,6 +26,8 @@ struct Cleanup : TermFun
virtual ATerm operator () (ATerm e)
{
+ checkInterrupt();
+
ATMatcher m;
string s;
diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc
index 24bedb3fb..17d4dda67 100644
--- a/src/libmain/shared.cc
+++ b/src/libmain/shared.cc
@@ -12,6 +12,12 @@ extern "C" {
#include "config.h"
+void sigintHandler(int signo)
+{
+ _isInterrupted = 1;
+}
+
+
/* Initialize and reorder arguments, then call the actual argument
processor. */
static void initAndRun(int argc, char * * argv)
@@ -23,6 +29,15 @@ static void initAndRun(int argc, char * * argv)
nixStateDir = (string) NIX_STATE_DIR;
nixDBPath = (string) NIX_STATE_DIR + "/db";
+ /* Catch SIGINT. */
+ struct sigaction act, oact;
+ act.sa_handler = sigintHandler;
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ if (sigaction(SIGINT, &act, &oact))
+ throw SysError("installing handler for SIGINT");
+ printMsg(lvlError, "SIG HANDLER INSTALLED");
+
/* Put the arguments in a vector. */
Strings args, remaining;
while (argc--) args.push_back(*argv++);
diff --git a/src/libstore/db.cc b/src/libstore/db.cc
index c89d6b197..d2a002638 100644
--- a/src/libstore/db.cc
+++ b/src/libstore/db.cc
@@ -80,6 +80,7 @@ void Transaction::moveTo(Transaction & t)
void Database::requireEnv()
{
+ checkInterrupt();
if (!env) throw Error("database environment not open");
}
@@ -310,6 +311,8 @@ TableId Database::openTable(const string & tableName)
bool Database::queryString(const Transaction & txn, TableId table,
const string & key, string & data)
{
+ checkInterrupt();
+
try {
Db * db = getDb(table);
@@ -367,6 +370,7 @@ bool Database::queryStrings(const Transaction & txn, TableId table,
void Database::setString(const Transaction & txn, TableId table,
const string & key, const string & data)
{
+ checkInterrupt();
try {
Db * db = getDb(table);
Dbt kt((void *) key.c_str(), key.length());
@@ -402,6 +406,7 @@ void Database::setStrings(const Transaction & txn, TableId table,
void Database::delPair(const Transaction & txn, TableId table,
const string & key)
{
+ checkInterrupt();
try {
Db * db = getDb(table);
Dbt kt((void *) key.c_str(), key.length());
@@ -423,9 +428,11 @@ void Database::enumTable(const Transaction & txn, TableId table,
DestroyDbc destroyDbc(dbc);
Dbt kt, dt;
- while (dbc->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND)
+ while (dbc->get(&kt, &dt, DB_NEXT) != DB_NOTFOUND) {
+ checkInterrupt();
keys.push_back(
string((char *) kt.get_data(), kt.get_size()));
+ }
} catch (DbException e) { rethrow(e); }
}
diff --git a/src/libstore/exec.cc b/src/libstore/exec.cc
index b25423b44..01577143d 100644
--- a/src/libstore/exec.cc
+++ b/src/libstore/exec.cc
@@ -108,7 +108,9 @@ void runProgram(const string & program,
int status;
if (waitpid(pid, &status, 0) != pid)
throw Error("unable to wait for child");
-
+
+ checkInterrupt();
+
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
if (keepFailed) {
printMsg(lvlTalkative,
diff --git a/src/libstore/normalise.cc b/src/libstore/normalise.cc
index 7ef45e292..51f90207e 100644
--- a/src/libstore/normalise.cc
+++ b/src/libstore/normalise.cc
@@ -96,6 +96,7 @@ Path normaliseStoreExpr(const Path & _nePath, PathSet pending)
for (PathSet::iterator i = ne.derivation.inputs.begin();
i != ne.derivation.inputs.end(); i++)
{
+ checkInterrupt();
Path nfPath = normaliseStoreExpr(*i, pending);
realiseClosure(nfPath, pending);
/* !!! nfPath should be a root of the garbage collector while
@@ -193,6 +194,7 @@ Path normaliseStoreExpr(const Path & _nePath, PathSet pending)
for (Paths::iterator j = refPaths.begin();
j != refPaths.end(); j++)
{
+ checkInterrupt();
Path path = *j;
elem.refs.insert(path);
if (inClosures.find(path) != inClosures.end())
@@ -209,6 +211,7 @@ Path normaliseStoreExpr(const Path & _nePath, PathSet pending)
PathSet donePaths;
while (!usedPaths.empty()) {
+ checkInterrupt();
PathSet::iterator i = usedPaths.begin();
Path path = *i;
usedPaths.erase(i);
@@ -291,6 +294,7 @@ void ensurePath(const Path & path, PathSet pending)
for (Paths::iterator i = subPaths.begin();
i != subPaths.end(); i++)
{
+ checkInterrupt();
try {
normaliseStoreExpr(*i, pending);
if (isValidPath(path)) return;
@@ -337,6 +341,8 @@ static void requisitesWorker(const Path & nePath,
bool includeExprs, bool includeSuccessors,
PathSet & paths, PathSet & doneSet)
{
+ checkInterrupt();
+
if (doneSet.find(nePath) != doneSet.end()) return;
doneSet.insert(nePath);
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index 321e965bb..d4f980c64 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -19,11 +19,14 @@ bool lockFile(int fd, LockType lockType, bool wait)
lock.l_len = 0; /* entire file */
if (wait) {
- while (fcntl(fd, F_SETLKW, &lock) != 0)
+ while (fcntl(fd, F_SETLKW, &lock) != 0) {
+ checkInterrupt();
if (errno != EINTR)
throw SysError(format("acquiring/releasing lock"));
+ }
} else {
while (fcntl(fd, F_SETLK, &lock) != 0) {
+ checkInterrupt();
if (errno == EACCES || errno == EAGAIN) return false;
if (errno != EINTR)
throw SysError(format("acquiring/releasing lock"));
@@ -55,6 +58,7 @@ PathLocks::PathLocks(const PathSet & _paths)
/* Acquire the lock for each path. */
for (Paths::iterator i = paths.begin(); i != paths.end(); i++) {
+ checkInterrupt();
Path path = *i;
Path lockPath = path + ".lock";
@@ -87,6 +91,7 @@ PathLocks::~PathLocks()
close(*i);
for (Paths::iterator i = paths.begin(); i != paths.end(); i++) {
+ checkInterrupt();
if (deletePaths) {
/* This is not safe in general! */
unlink(i->c_str());
diff --git a/src/libstore/references.cc b/src/libstore/references.cc
index 2daf4d4f4..9b20b980a 100644
--- a/src/libstore/references.cc
+++ b/src/libstore/references.cc
@@ -17,6 +17,7 @@ static void search(const string & s,
for (Strings::iterator i = ids.begin();
i != ids.end(); )
{
+ checkInterrupt();
if (s.find(*i) == string::npos)
i++;
else {
@@ -31,6 +32,8 @@ static void search(const string & s,
void checkPath(const string & path,
Strings & ids, Strings & seen)
{
+ checkInterrupt();
+
struct stat st;
if (lstat(path.c_str(), &st))
throw SysError(format("getting attributes of path `%1%'") % path);
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index c1d95ab8c..4cd77796e 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -133,7 +133,7 @@ void copyPath(const Path & src, const Path & dst)
source.fd = fds[0];
restorePath(dst, source);
_exit(0);
- } catch (exception & e) {
+ } catch (exception & e) {
cerr << "error: " << e.what() << endl;
}
_exit(1);
diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc
index 90a039164..2b8fb2f10 100644
--- a/src/libutil/archive.cc
+++ b/src/libutil/archive.cc
@@ -83,6 +83,7 @@ static void dumpContents(const Path & path, unsigned int size,
unsigned int total = 0;
ssize_t n;
while ((n = read(fd, buf, sizeof(buf)))) {
+ checkInterrupt();
if (n == -1) throw SysError("reading file " + path);
total += n;
sink(buf, n);
@@ -200,6 +201,8 @@ static void restoreEntry(const Path & path, RestoreSource & source)
if (s != "(") throw badArchive("expected open tag");
while (1) {
+ checkInterrupt();
+
s = readString(source);
if (s == ")") {
@@ -224,6 +227,7 @@ static void restoreContents(int fd, const Path & path, RestoreSource & source)
unsigned char buf[65536];
while (left) {
+ checkInterrupt();
unsigned int n = sizeof(buf);
if (n > left) n = left;
source(buf, n);
@@ -247,6 +251,8 @@ static void restore(const Path & path, RestoreSource & source)
AutoCloseFD fd;
while (1) {
+ checkInterrupt();
+
s = readString(source);
if (s == ")") {
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 28e276a32..5c8b7279c 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -132,6 +132,7 @@ Strings readDirectory(const Path & path)
struct dirent * dirent;
while (errno = 0, dirent = readdir(dir)) { /* sic */
+ checkInterrupt();
string name = dirent->d_name;
if (name == "." || name == "..") continue;
names.push_back(name);
@@ -144,6 +145,8 @@ Strings readDirectory(const Path & path)
void deletePath(const Path & path)
{
+ checkInterrupt();
+
printMsg(lvlVomit, format("deleting path `%1%'") % path);
struct stat st;
@@ -170,6 +173,8 @@ void deletePath(const Path & path)
void makePathReadOnly(const Path & path)
{
+ checkInterrupt();
+
struct stat st;
if (lstat(path.c_str(), &st))
throw SysError(format("getting attributes of path `%1%'") % path);
@@ -199,6 +204,7 @@ static Path tempName()
Path createTempDir()
{
while (1) {
+ checkInterrupt();
Path tmpDir = tempName();
if (mkdir(tmpDir.c_str(), 0777) == 0) return tmpDir;
if (errno != EEXIST)
@@ -246,6 +252,7 @@ void Nest::open(Verbosity level, const format & f)
void printMsg_(Verbosity level, const format & f)
{
+ checkInterrupt();
if (level > verbosity) return;
string spaces;
for (int i = 0; i < nestingLevel; i++)
@@ -257,6 +264,7 @@ void printMsg_(Verbosity level, const format & f)
void readFull(int fd, unsigned char * buf, size_t count)
{
while (count) {
+ checkInterrupt();
ssize_t res = read(fd, (char *) buf, count);
if (res == -1) throw SysError("reading from file");
if (res == 0) throw Error("unexpected end-of-file");
@@ -269,6 +277,7 @@ void readFull(int fd, unsigned char * buf, size_t count)
void writeFull(int fd, const unsigned char * buf, size_t count)
{
while (count) {
+ checkInterrupt();
ssize_t res = write(fd, (char *) buf, count);
if (res == -1) throw SysError("writing to file");
count -= res;
@@ -344,3 +353,11 @@ AutoCloseDir::operator DIR *()
return dir;
}
+
+volatile sig_atomic_t _isInterrupted = 0;
+
+void _interrupted()
+{
+ _isInterrupted = 0;
+ throw Error("interrupted by the user");
+}
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 5d27ac1bd..34fff003b 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -9,6 +9,7 @@
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
+#include <signal.h>
#include <boost/format.hpp>
@@ -179,4 +180,16 @@ public:
};
+/* User interruption. */
+
+extern volatile sig_atomic_t _isInterrupted;
+
+void _interrupted();
+
+void inline checkInterrupt()
+{
+ if (_isInterrupted) _interrupted();
+}
+
+
#endif /* !__UTIL_H */