]> git.neil.brown.name Git - edlib.git/commitdiff
Wait for processes we fork.
authorNeilBrown <neil@brown.name>
Mon, 29 May 2023 11:37:26 +0000 (21:37 +1000)
committerNeilBrown <neil@brown.name>
Thu, 8 Jun 2023 10:38:57 +0000 (20:38 +1000)
Keep track of the xdg-open processes we fork, and wait for them as
appropriate.

Also make sure we catch the correct TimeoutExpired except when a notmuch
search takes too long, so we can kill and wait for the process.

Signed-off-by: NeilBrown <neil@brown.name>
DOC/TODO.md
display-ncurses.c
display-x11-xcb.c
python/display-pygtk.py
python/module-notmuch.py

index 520598c2f011e586b92ea59440264c2f97725f0e..ae73924ddb649a61e76896d4360016541785c18b 100644 (file)
@@ -62,6 +62,7 @@ Current priorities
 Bugs to be fixed
 ----------------
 
+- [ ] notmuch reply should interpolate the first *visible* text part
 - [X] multipart must handle Notify:Close better.  It should NULL out the
       pointer to the pane, and always check it isn't NULL.
 - [X] I cannot dup a mark in a mark:moving handler.  That is too
@@ -129,7 +130,7 @@ Bugs to be fixed
       scaling.
 - [ ] stop consistency checking a text doc when it gets "big" ??
 - [ ] auto-sign emails..
-- [ ] be sure to wait for xdg-open etc.
+- [X] be sure to wait for xdg-open etc.
 - [ ] things slow down after lots of edits.  Maybe track
       number of chunk, marks, undos etc and display them somewhere
 - [?] Make doesn't follow llog_reader.c:723:6: when it have seen
index 7cd08082905dfbd7d8433c957659756d037a454b..3f89bdf848ec888b56036c90cdb8c67277e41f93 100644 (file)
@@ -32,6 +32,7 @@
 #include <ctype.h>
 #include <signal.h>
 #include <sys/ioctl.h>
+#include <sys/wait.h>
 #include <netdb.h>
 
 #include <wand/MagickWand.h>
@@ -74,6 +75,11 @@ struct display_data {
        char                    *paste_latest;
        int                     paste_pending;
 
+       struct pids {
+               pid_t           pid;
+               struct pids     *next;
+       }                       *pids;
+
        char                    *rs1, *rs2, *rs3, *clear;
        char                    attr_buf[1024];
        #ifdef RECORD_REPLAY
@@ -491,6 +497,20 @@ static char *fnormalize(struct pane *p safe, const char *str) safe
        return ret ?: "_";
 }
 
+static void wait_for(struct display_data *dd safe)
+{
+       struct pids **pp = &dd->pids;
+
+       while (*pp) {
+               struct pids *p = *pp;
+               if (waitpid(p->pid, NULL, WNOHANG) > 0) {
+                       *pp = p->next;
+                       free(p);
+               } else
+                       pp = &p->next;
+       }
+}
+
 DEF_CMD(nc_external_viewer)
 {
        struct pane *p = ci->home;
@@ -508,6 +528,7 @@ DEF_CMD(nc_external_viewer)
        if (!path)
                return Enoarg;
        if (disp && *disp) {
+               struct pids *pds;
                switch (pid = fork()) {
                case -1:
                        return Efail;
@@ -526,9 +547,13 @@ DEF_CMD(nc_external_viewer)
                        execlp("xdg-open", "xdg-open", path, NULL);
                        exit(1);
                default: /* parent */
-                       /* FIXME record pid?? */
+                       pds = malloc(sizeof(*pds));
+                       pds->pid = pid;
+                       pds->next = dd->pids;
+                       dd->pids = pds;
                        break;
                }
+               wait_for(dd);
                return 1;
        }
        /* handle no-display case */
@@ -1675,6 +1700,7 @@ REDEF_CMD(input_handle)
        if (!(void*)p->data)
                /* already closed */
                return 0;
+       wait_for(dd);
        set_screen(p);
        while ((is_keycode = get_wch(&c)) != ERR) {
                if (paste_recv(p, is_keycode, c))
index cff553628fbe888801b418dc95c9ea5131aef2a2..6d124a077ed91a21f3ca3597b287ccc6633ac118 100644 (file)
@@ -15,6 +15,7 @@
 #include <string.h>
 #include <xcb/xcb.h>
 #include <stdarg.h>
+#include <sys/wait.h>
 #ifndef __CHECKER__
 #include <xcb/xkb.h>
 #else
@@ -204,6 +205,11 @@ struct xcb_data {
        struct xkb_compose_table *compose_table;
        struct xkb_keymap       *xkb_keymap;
 
+       struct pids {
+               pid_t           pid;
+               struct pids     *next;
+       }                       *pids;
+
        /* FIXME use hash?? */
        struct panes {
                struct panes    *next;
@@ -458,10 +464,25 @@ DEF_CMD(xcb_set_noclose)
        return 1;
 }
 
+static void wait_for(struct xcb_data *xd safe)
+{
+       struct pids **pp = &xd->pids;
+
+       while (*pp) {
+               struct pids *p = *pp;
+               if (waitpid(p->pid, NULL, WNOHANG) > 0) {
+                       *pp = p->next;
+                       free(p);
+               } else
+                       pp = &p->next;
+       }
+}
+
 DEF_CMD(xcb_external_viewer)
 {
        struct xcb_data *xd = ci->home->data;
        const char *path = ci->str;
+       struct pids *p;
        int pid;
        int fd;
 
@@ -485,8 +506,13 @@ DEF_CMD(xcb_external_viewer)
                execlp("xdg-open", "xdg-open", path, NULL);
                exit(1);
        default: /* parent */
+               p = malloc(sizeof(*p));
+               p->pid = pid;
+               p->next = xd->pids;
+               xd->pids = p;
                break;
        }
+       wait_for(xd);
        return 1;
 }
 
@@ -1594,6 +1620,7 @@ DEF_CMD(xcb_input)
        xcb_generic_event_t *ev;
        int ret = 1;
 
+       wait_for(xd);
        if (ci->num < 0)
                /* This is a poll - only return 1 on something happening */
                ret = Efalse;
index eb8ae28f47075699e51468e6ac259a93fabb9e03..f33d5b5dc11683be2d5201dda9f275a0bb3c46d1 100644 (file)
@@ -16,6 +16,26 @@ gi.require_version('PangoCairo', '1.0')
 gi.require_foreign("cairo")
 from gi.repository import Gtk, Gdk, Pango, PangoCairo, GdkPixbuf, Gio
 
+def wait_for(p):
+    try:
+        r = os.read(p.stdout.fileno(), 4096)
+    except IOError:
+        # nothing to read yet
+        return 1
+    if r:
+        # not eof yet
+        return 1
+    p.communicate()
+    # stop waiting
+    return edlib.Efalse
+
+def wait_on(self, p):
+    # wait on pipe for exit
+    fd = self.pipe.stdout.fileno()
+    fl = fcntl.fcntl(fd, fcntl.F_GETFL);
+    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
+    self.call("event:read", fd, lambda key, **a: wait_for(p))
+
 class EdDisplay(edlib.Pane):
     def __init__(self, focus, display):
         edlib.Pane.__init__(self, focus, z=1)
@@ -92,8 +112,12 @@ class EdDisplay(edlib.Pane):
         env = os.environ.copy()
         env['DISPLAY'] = disp
 
-        subprocess.Popen(["xdg-open", str], env=env,
+        p = subprocess.Popen(["xdg-open", str], env=env,
+                         stdin = subprocess.DEVNULL,
+                         stdout = subprocess.PIPE,
                          stderr = subprocess.DEVNULL)
+        if p:
+            wait_on(self, p)
         return 1
 
     def handle_close(self, key, **a):
index c3b2c42da2e33267ccf56458b0654e6f69ba8133..37384e87938067300c5af1a41b437698cc53cd1a 100644 (file)
@@ -28,7 +28,7 @@
 # "query.misc-list" is a subset of current-list for which query:current should not
 # be assumed.
 
-from subprocess import Popen, PIPE, DEVNULL
+from subprocess import Popen, PIPE, DEVNULL, TimeoutExpired
 import re
 import os
 import os.path