[gimp] app: add gimp_spawn_async()



commit 0f2df18ddee944f5c27a283151d31e9be451d841
Author: Ell <ell_se yahoo com>
Date:   Mon Mar 5 01:32:53 2018 -0500

    app: add gimp_spawn_async()
    
    gimp_spawn_async() is similar to, but more limited than,
    g_spawn_sync().  Unlike the latter, gimp_spawn_async() uses
    vfork(), instead of fork(), when possible.
    
    On Linux, a process that uses large amounts of memory (as GIMP may)
    can hang during a fork() if overcommitting is enabled, and there's
    not enough memroy.  Using vfork() avoids that, since it doesn't
    duplicate the parent's address space.

 app/core/Makefile.am  |    2 +
 app/core/gimp-spawn.c |  222 +++++++++++++++++++++++++++++++++++++++++++++++++
 app/core/gimp-spawn.h |   32 +++++++
 configure.ac          |    5 +
 po/POTFILES.in        |    1 +
 5 files changed, 262 insertions(+), 0 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index c3be33a..a751ffb 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -54,6 +54,8 @@ libappcore_a_sources = \
        gimp-palettes.h                         \
        gimp-parasites.c                        \
        gimp-parasites.h                        \
+       gimp-spawn.c                            \
+       gimp-spawn.h                            \
        gimp-tags.c                             \
        gimp-tags.h                             \
        gimp-templates.c                        \
diff --git a/app/core/gimp-spawn.c b/app/core/gimp-spawn.c
new file mode 100644
index 0000000..26fec13
--- /dev/null
+++ b/app/core/gimp-spawn.c
@@ -0,0 +1,222 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimp-spawn.c
+ * Copyright (C) 2018 Ell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_VFORK
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+
+#include <glib-object.h>
+
+#include "core-types.h"
+
+#include "gimp-spawn.h"
+
+#include "gimp-intl.h"
+
+
+/* copied from glib */
+static gint
+exec_err_to_g_error (gint en)
+{
+  switch (en)
+    {
+#ifdef EACCES
+    case EACCES:
+      return G_SPAWN_ERROR_ACCES;
+      break;
+#endif
+
+#ifdef EPERM
+    case EPERM:
+      return G_SPAWN_ERROR_PERM;
+      break;
+#endif
+
+#ifdef E2BIG
+    case E2BIG:
+      return G_SPAWN_ERROR_TOO_BIG;
+      break;
+#endif
+
+#ifdef ENOEXEC
+    case ENOEXEC:
+      return G_SPAWN_ERROR_NOEXEC;
+      break;
+#endif
+
+#ifdef ENAMETOOLONG
+    case ENAMETOOLONG:
+      return G_SPAWN_ERROR_NAMETOOLONG;
+      break;
+#endif
+
+#ifdef ENOENT
+    case ENOENT:
+      return G_SPAWN_ERROR_NOENT;
+      break;
+#endif
+
+#ifdef ENOMEM
+    case ENOMEM:
+      return G_SPAWN_ERROR_NOMEM;
+      break;
+#endif
+
+#ifdef ENOTDIR
+    case ENOTDIR:
+      return G_SPAWN_ERROR_NOTDIR;
+      break;
+#endif
+
+#ifdef ELOOP
+    case ELOOP:
+      return G_SPAWN_ERROR_LOOP;
+      break;
+#endif
+
+#ifdef ETXTBUSY
+    case ETXTBUSY:
+      return G_SPAWN_ERROR_TXTBUSY;
+      break;
+#endif
+
+#ifdef EIO
+    case EIO:
+      return G_SPAWN_ERROR_IO;
+      break;
+#endif
+
+#ifdef ENFILE
+    case ENFILE:
+      return G_SPAWN_ERROR_NFILE;
+      break;
+#endif
+
+#ifdef EMFILE
+    case EMFILE:
+      return G_SPAWN_ERROR_MFILE;
+      break;
+#endif
+
+#ifdef EINVAL
+    case EINVAL:
+      return G_SPAWN_ERROR_INVAL;
+      break;
+#endif
+
+#ifdef EISDIR
+    case EISDIR:
+      return G_SPAWN_ERROR_ISDIR;
+      break;
+#endif
+
+#ifdef ELIBBAD
+    case ELIBBAD:
+      return G_SPAWN_ERROR_LIBBAD;
+      break;
+#endif
+
+    default:
+      return G_SPAWN_ERROR_FAILED;
+      break;
+    }
+}
+
+gboolean
+gimp_spawn_async (gchar       **argv,
+                  gchar       **envp,
+                  GSpawnFlags   flags,
+                  GPid         *child_pid,
+                  GError      **error)
+{
+#ifdef HAVE_VFORK
+  if (flags == (G_SPAWN_LEAVE_DESCRIPTORS_OPEN |
+                G_SPAWN_DO_NOT_REAP_CHILD      |
+                G_SPAWN_CHILD_INHERITS_STDIN))
+    {
+      pid_t pid;
+
+      pid = vfork ();
+
+      if (pid < 0)
+        {
+          gint errsv = errno;
+
+          g_set_error (error,
+                       G_SPAWN_ERROR,
+                       G_SPAWN_ERROR_FORK,
+                       _("Failed to fork (%s)"),
+                       g_strerror (errsv));
+
+          return FALSE;
+        }
+      else if (pid == 0)
+        {
+          if (envp)
+            execve (argv[0], argv, envp);
+          else
+            execv (argv[0], argv);
+
+          _exit (errno);
+        }
+      else
+        {
+          int   status = -1;
+          pid_t result;
+
+          result = waitpid (pid, &status, WNOHANG);
+
+          if (result)
+            {
+              if (result < 0)
+                {
+                  g_warning ("waitpid() should not fail in "
+                             "gimp_spawn_async()");
+                }
+
+              if (WIFEXITED (status))
+                status = WEXITSTATUS (status);
+              else
+                status = -1;
+
+              g_set_error (error,
+                           G_SPAWN_ERROR,
+                           exec_err_to_g_error (status),
+                           _("Failed to execute child process ā€œ%sā€ (%s)"),
+                           argv[0],
+                           g_strerror (status));
+
+              return FALSE;
+            }
+
+          if (child_pid) *child_pid = pid;
+
+          return TRUE;
+        }
+    }
+#endif /* HAVE_VFORK */
+
+  return g_spawn_async (NULL, argv, envp, flags, NULL, NULL, child_pid, error);
+}
diff --git a/app/core/gimp-spawn.h b/app/core/gimp-spawn.h
new file mode 100644
index 0000000..432296e
--- /dev/null
+++ b/app/core/gimp-spawn.h
@@ -0,0 +1,32 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimp-spawn.h
+ * Copyright (C) 2018 Ell
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_SPAWN_H__
+#define __GIMP_SPAWN_H__
+
+
+gboolean   gimp_spawn_async (gchar       **argv,
+                             gchar       **envp,
+                             GSpawnFlags   flags,
+                             GPid         *child_pid,
+                             GError      **error);
+
+
+#endif /* __GIMP_SPAWN_H__ */
diff --git a/configure.ac b/configure.ac
index 14c2e20..c9d65bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -960,6 +960,11 @@ AC_CHECK_FUNC(rint, AC_DEFINE(HAVE_RINT, 1,
     AC_DEFINE(HAVE_RINT)])])
 
 
+# check for vfork
+AC_CHECK_FUNCS(vfork, ,)
+AC_SUBST(HAVE_VFORK)
+
+
 ##############################
 # Check for attributes we need
 ##############################
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 9099597..d20a69e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -110,6 +110,7 @@ app/core/gimp-gui.c
 app/core/gimp-internal-data.c
 app/core/gimp-modules.c
 app/core/gimp-palettes.c
+app/core/gimp-spawn.c
 app/core/gimp-tags.c
 app/core/gimp-units.c
 app/core/gimp-user-install.c


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