summaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
authorNRK <nrk@disroot.org>2022-06-22 05:28:07 +0200
committerNRK <nrk@disroot.org>2023-01-09 06:07:24 +0100
commit49d11f0d1fae43ae1e5f61204ed051e889062767 (patch)
tree39950a5f0de40b7048a171025c2ff3f8db43bee2 /main.c
parent76c2b81b6077702d3bbd9726b698cd8b6547fc5e (diff)
downloadnsxiv-49d11f0d1fae43ae1e5f61204ed051e889062767.tar.zst
spawn(): improve performance and simplify API
posix_spawn() is designed especially for this purpose, and thus it's much more lightweight and efficient than manually fork/dup/exec-ing. on my system, it improves the performance of spawn() by about 10x. given that we make frequent calls to potentially multiple scripts, the increased efficiency will add up overtime. using posix_spawn() also simplifies the logic quite a bit, despite the very verbose function names. however it does make cleanup a bit more complicated. this patch uses the linux kernel style cleanup strategy [0] (which I'm personally not a huge fan of, but it fits this situation quite nicely) with a "stack-like" unwinding via `goto`-s. additionally simplify the spawn() API by taking in {read,write}fd pointers and returning the pid instead of using some custom struct. this coincidently also fixes #299 [0]: https://www.kernel.org/doc/html/v4.10/process/coding-style.html?highlight=goto#centralized-exiting-of-functions
Diffstat (limited to 'main.c')
-rw-r--r--main.c34
1 files changed, 13 insertions, 21 deletions
diff --git a/main.c b/main.c
index 8ee5b9d..3312503 100644
--- a/main.c
+++ b/main.c
@@ -277,9 +277,9 @@ static bool check_timeouts(int *t)
static size_t get_win_title(char *buf, size_t len)
{
char *argv[8];
- spawn_t pfd;
char w[12] = "", h[12] = "", z[12] = "", fidx[12], fcnt[12];
ssize_t n = -1;
+ int readfd;
if (wintitle.f.err || buf == NULL || len == 0)
return 0;
@@ -293,11 +293,10 @@ static size_t get_win_title(char *buf, size_t len)
snprintf(fcnt, ARRLEN(fcnt), "%d", filecnt);
construct_argv(argv, ARRLEN(argv), wintitle.f.cmd, files[fileidx].path,
fidx, fcnt, w, h, z, NULL);
- pfd = spawn(wintitle.f.cmd, argv, X_READ);
- if (pfd.readfd >= 0) {
- if ((n = read(pfd.readfd, buf, len-1)) > 0)
+ if (spawn(&readfd, NULL, argv) > 0) {
+ if ((n = read(readfd, buf, len-1)) > 0)
buf[n] = '\0';
- close(pfd.readfd);
+ close(readfd);
}
return MAX(0, n);
@@ -314,9 +313,7 @@ void close_info(void)
void open_info(void)
{
- spawn_t pfd;
- char w[12] = "", h[12] = "";
- char *argv[6];
+ char *argv[6], w[12] = "", h[12] = "";
char *cmd = mode == MODE_IMAGE ? info.f.cmd : info.ft.cmd;
bool ferr = mode == MODE_IMAGE ? info.f.err : info.ft.err;
@@ -329,12 +326,8 @@ void open_info(void)
}
construct_argv(argv, ARRLEN(argv), cmd, files[fileidx].name, w, h,
files[fileidx].path, NULL);
- pfd = spawn(cmd, argv, X_READ);
- if (pfd.readfd >= 0) {
- fcntl(pfd.readfd, F_SETFL, O_NONBLOCK);
- info.fd = pfd.readfd;
- info.pid = pfd.pid;
- }
+ if ((info.pid = spawn(&info.fd, NULL, argv)) > 0)
+ fcntl(info.fd, F_SETFL, O_NONBLOCK);
}
static void read_info(void)
@@ -579,13 +572,13 @@ static bool run_key_handler(const char *key, unsigned int mask)
FILE *pfs;
bool marked = mode == MODE_THUMB && markcnt > 0;
bool changed = false;
- int f, i;
+ pid_t pid;
+ int writefd, f, i;
int fcnt = marked ? markcnt : 1;
char kstr[32];
struct stat *oldst, st;
XEvent dump;
char *argv[3];
- spawn_t pfd;
if (keyhandler.f.err) {
if (!keyhandler.warned) {
@@ -608,12 +601,11 @@ static bool run_key_handler(const char *key, unsigned int mask)
mask & Mod1Mask ? "M-" : "",
mask & ShiftMask ? "S-" : "", key);
construct_argv(argv, ARRLEN(argv), keyhandler.f.cmd, kstr, NULL);
- pfd = spawn(keyhandler.f.cmd, argv, X_WRITE);
- if (pfd.writefd < 0)
+ if ((pid = spawn(NULL, &writefd, argv)) < 0)
return false;
- if ((pfs = fdopen(pfd.writefd, "w")) == NULL) {
+ if ((pfs = fdopen(writefd, "w")) == NULL) {
error(0, errno, "open pipe");
- close(pfd.writefd);
+ close(writefd);
return false;
}
@@ -626,7 +618,7 @@ static bool run_key_handler(const char *key, unsigned int mask)
}
}
fclose(pfs);
- while (waitpid(pfd.pid, NULL, 0) == -1 && errno == EINTR);
+ while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
for (f = i = 0; f < fcnt; i++) {
if ((marked && (files[i].flags & FF_MARK)) || (!marked && i == fileidx)) {