[newlib-cygwin] forkables: simplify disabling via shm

Corinna Vinschen corinna@sourceware.org
Fri Feb 8 11:38:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=135577f708a07405d1cd80880430429a9beb1041

commit 135577f708a07405d1cd80880430429a9beb1041
Author: Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
Date:   Wed Mar 1 10:19:37 2017 +0100

    forkables: simplify disabling via shm
    
    * Rename cygwin_shared->prefer_forkable_hardlinks to
      forkable_hardlink_support, with values
      0 for Unknown, 1 for Supported, -1 for Unsupported.
      Upon first dll loaded ever, dll_list::forkable_ntnamesize checks the
      /var/run/cygfork directory to both exist and reside on NTFS, setting
      cygwin_shared->forkable_hardlink_support accordingly.
    * Replace enum forkables_needs by bool forkables_created: Set
      to True by request_forkables after creating forkable hardlinks.

Diff:
---
 winsup/cygwin/dll_init.h               |  21 ++--
 winsup/cygwin/forkable.cc              | 185 ++++++++++-----------------------
 winsup/cygwin/include/cygwin/version.h |   2 +-
 winsup/cygwin/shared.cc                |   1 +
 winsup/cygwin/shared_info.h            |   4 +-
 5 files changed, 65 insertions(+), 148 deletions(-)

diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h
index 45f71cb..5c4cc0b 100644
--- a/winsup/cygwin/dll_init.h
+++ b/winsup/cygwin/dll_init.h
@@ -87,17 +87,9 @@ struct dll
 class dll_list
 {
   /* forkables */
-  enum
-    {
-      forkables_unknown,
-      forkables_impossible,
-      forkables_disabled,
-      forkables_needless,
-      forkables_needed,
-      forkables_created,
-    }
-    forkables_needs;
+  bool forkables_supported ();
   DWORD forkables_dirx_size;
+  bool forkables_created;
   PWCHAR forkables_dirx_ntname;
   PWCHAR forkables_mutex_name;
   HANDLE forkables_mutex;
@@ -160,10 +152,11 @@ public:
   void cleanup_forkables ();
   bool setup_forkables (bool with_forkables)
   {
-    if (forkables_needs == forkables_impossible)
-      return true; /* short cut to not retry fork */
-    /* Once used, always use forkables in current process chain. */
-    if (forkables_needs != forkables_unknown)
+    if (!forkables_supported ())
+      return true; /* no need to retry fork */
+    if (forkables_created)
+      /* Once created, use forkables in current
+	 process chain on first fork try already. */
       with_forkables = true;
     if (with_forkables)
       request_forkables ();
diff --git a/winsup/cygwin/forkable.cc b/winsup/cygwin/forkable.cc
index c569b0f..05b2285 100644
--- a/winsup/cygwin/forkable.cc
+++ b/winsup/cygwin/forkable.cc
@@ -501,17 +501,56 @@ dll::create_forkable ()
   return false;
 }
 
+bool
+dll_list::forkables_supported ()
+{
+  return cygwin_shared->forkable_hardlink_support >= 0;
+}
+
 /* return the number of characters necessary to store one forkable name */
 size_t
 dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modname)
 {
   /* per process, this is the first forkables-method ever called */
-  if (forkables_needs == forkables_unknown &&
-      !cygwin_shared->prefer_forkable_hardlinks)
-      forkables_needs = forkables_impossible; /* short cut */
+  if (cygwin_shared->forkable_hardlink_support == 0) /* Unknown */
+    {
+      /* check existence of forkables dir */
+      PWCHAR pbuf = nt_max_path_buf ();
+      for (namepart const *part = forkable_nameparts; part->text; ++part)
+	{
+	  if (part->textfunc)
+	    pbuf += part->textfunc (pbuf, -1);
+	  else
+	    pbuf += __small_swprintf (pbuf, L"%W", part->text);
+	  if (part->mutex_from_dir)
+	    break; /* up to first mutex-naming dir */
+	}
+      pbuf = nt_max_path_buf ();
 
-  if (forkables_needs == forkables_impossible)
-    return 0;
+      UNICODE_STRING fn;
+      RtlInitUnicodeString (&fn, pbuf);
+
+      HANDLE dh = INVALID_HANDLE_VALUE;
+      fs_info fsi;
+      if (fsi.update (&fn, NULL) &&
+/* FIXME: !fsi.is_readonly () && */
+	  fsi.is_ntfs ())
+	dh = ntopenfile (pbuf, NULL, FILE_DIRECTORY_FILE);
+      if (dh != INVALID_HANDLE_VALUE)
+	{
+	  cygwin_shared->forkable_hardlink_support = 1; /* Yes */
+	  NtClose (dh);
+	  debug_printf ("enabled");
+	}
+      else
+	{
+	  cygwin_shared->forkable_hardlink_support = -1; /* No */
+	  debug_printf ("disabled, missing or not on NTFS %W", fn.Buffer);
+	}
+    }
+
+  if (!forkables_supported ())
+      return 0;
 
   if (!forkables_dirx_size)
     {
@@ -560,9 +599,6 @@ dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modnam
 void
 dll_list::prepare_forkables_nomination ()
 {
-  if (!forkables_dirx_ntname)
-    return;
-
   dll *d = &dlls.start;
   while ((d = d->next))
     stat_real_file_once (d); /* uses nt_max_path_buf () */
@@ -627,106 +663,19 @@ dll_list::prepare_forkables_nomination ()
 void
 dll_list::update_forkables_needs ()
 {
-  dll *d;
-
-  if (forkables_needs == forkables_unknown)
-    {
-      /* check if filesystem of forkables dir is NTFS */
-      PWCHAR pbuf = nt_max_path_buf ();
-      for (namepart const *part = forkable_nameparts; part->text; ++part)
-	{
-	  if (part->mutex_from_dir)
-	    break; /* leading non-mutex-naming dirs, must exist anyway */
-	  if (part->textfunc)
-	    pbuf += part->textfunc (pbuf, -1);
-	  else
-	    pbuf += __small_swprintf (pbuf, L"%W", part->text);
-	}
-
-      UNICODE_STRING fn;
-      RtlInitUnicodeString (&fn, nt_max_path_buf ());
-
-      fs_info fsi;
-      if (fsi.update (&fn, NULL) &&
-/* FIXME: !fsi.is_readonly () && */
-	  fsi.is_ntfs ())
-	forkables_needs = forkables_disabled; /* check directory itself */
-      else
-	{
-	  debug_printf ("impossible, not on NTFS %W", fn.Buffer);
-	  forkables_needs = forkables_impossible;
-	  cygwin_shared->prefer_forkable_hardlinks = 0;
-	}
-    }
-
-  if (forkables_needs == forkables_impossible)
-    return; /* we have not created any hardlink, nothing to clean up */
-
-  if (forkables_needs == forkables_disabled ||
-      forkables_needs == forkables_needless ||
-      forkables_needs == forkables_created)
-    {
-      /* (re-)check existence of forkables dir */
-      PWCHAR pbuf = nt_max_path_buf ();
-      for (namepart const *part = forkable_nameparts; part->text; ++part)
-	{
-	  if (part->textfunc)
-	    pbuf += part->textfunc (pbuf, -1);
-	  else
-	    pbuf += __small_swprintf (pbuf, L"%W", part->text);
-	  if (part->mutex_from_dir)
-	    break; /* up to first mutex-naming dir */
-	}
-      pbuf = nt_max_path_buf ();
-
-      HANDLE dh = ntopenfile (pbuf, NULL, FILE_DIRECTORY_FILE);
-      if (dh != INVALID_HANDLE_VALUE)
-	{
-	  NtClose (dh);
-	  if (forkables_needs == forkables_disabled)
-	    forkables_needs = forkables_needless;
-	}
-      else if (forkables_needs != forkables_disabled)
-	{
-	  debug_printf ("disabled, disappearing %W", pbuf);
-	  close_mutex ();
-	  denominate_forkables ();
-	  forkables_needs = forkables_disabled;
-	}
-      else
-	debug_printf ("disabled, missing %W", pbuf);
-    }
-
-  if (forkables_needs == forkables_disabled)
-    return;
-
-  if (forkables_needs == forkables_created)
+  if (forkables_created)
     {
       /* already have created hardlinks in this process, ... */
-      forkables_needs = forkables_needless;
-      d = &start;
+      dll *d = &start;
       while ((d = d->next) != NULL)
 	if (d->forkable_ntname && !*d->forkable_ntname)
 	  {
 	    /* ... but another dll was loaded since last fork */
 	    debug_printf ("needed, since last fork loaded %W", d->ntname);
-	    forkables_needs = forkables_needed;
+	    forkables_created = false;
 	    break;
 	  }
     }
-
-  if (forkables_needs > forkables_needless)
-    return; /* no need to check anything else */
-
-  if (forkables_needs != forkables_needless)
-    {
-      /* paranoia */
-      system_printf ("WARNING: invalid forkables_needs value %d",
-		     forkables_needs);
-      return;
-    }
-
-  forkables_needs = forkables_needed;
 }
 
 /* Create the nominated forkable hardlinks and directories as necessary,
@@ -958,7 +907,7 @@ dll_list::close_mutex ()
 void
 dll_list::cleanup_forkables ()
 {
-  if (!forkables_dirx_ntname)
+  if (!forkables_supported ())
     return;
 
   bool locked = close_mutex ();
@@ -1034,58 +983,32 @@ dll_list::set_forkables_inheritance (bool inherit)
 void
 dll_list::request_forkables ()
 {
-  if (!forkables_dirx_ntname)
+  if (!forkables_supported ())
     return;
 
-  /* Even on forkables_impossible, keep the number of open handles
-     stable across the fork, and close them when releasing only. */
   prepare_forkables_nomination ();
 
   update_forkables_needs ();
 
   set_forkables_inheritance (true);
 
-  if (forkables_needs == forkables_disabled)
-    {
-      /* we do not support (re-)enabling on the fly */
-      forkables_needs = forkables_impossible;
-      cygwin_shared->prefer_forkable_hardlinks = 0;
-    }
-
-  if (forkables_needs <= forkables_needless)
-    return;
+  if (forkables_created)
+    return; /* nothing new to create */
 
   dll *d = &start;
   while ((d = d->next))
     d->nominate_forkable (forkables_dirx_ntname);
 
-  bool updated = update_forkables ();
-
-  if (!updated)
-    forkables_needs = forkables_needless;
-  else
-    forkables_needs = forkables_created;
+  if (update_forkables ())
+    forkables_created = true;
 }
 
 
 void
 dll_list::release_forkables ()
 {
-  if (!forkables_dirx_ntname)
+  if (!forkables_supported ())
     return;
 
   set_forkables_inheritance (false);
-
-  if (forkables_needs == forkables_impossible)
-    {
-      cleanup_forkables ();
-
-      dll *d = &start;
-      while ((d = d->next))
-	d->forkable_ntname = NULL;
-
-      cfree (forkables_dirx_ntname);
-      forkables_dirx_ntname = NULL;
-      forkables_mutex_name = NULL;
-    }
 }
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index f7ed351..8926d49 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -518,7 +518,7 @@ details. */
    regions.  It is incremented when incompatible changes are made to the shared
    memory region *or* to any named shared mutexes, semaphores, etc. */
 
-#define CYGWIN_VERSION_SHARED_DATA 6
+#define CYGWIN_VERSION_SHARED_DATA 5
 
 /* An identifier used in the names used to create shared objects.  The full
    names include the CYGWIN_VERSION_SHARED_DATA version as well as this
diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc
index e87f2f9..c939e0d 100644
--- a/winsup/cygwin/shared.cc
+++ b/winsup/cygwin/shared.cc
@@ -334,6 +334,7 @@ shared_info::initialize ()
       NtAllocateLocallyUniqueId (&luid);/* Initialize pid_src to a low    */
       InterlockedExchange (&pid_src,	/* random value to make start pid */
 		   luid.LowPart % 2048);/* less predictably               */
+      forkable_hardlink_support = 0;    /* 0: Unknown, 1: Yes, -1: No */
       /* Defer debug output printing the installation root and installation key
 	 up to this point.  Debug output except for system_printf requires
 	 the global shared memory to exist. */
diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h
index 8f0954f..307306c 100644
--- a/winsup/cygwin/shared_info.h
+++ b/winsup/cygwin/shared_info.h
@@ -33,7 +33,7 @@ public:
 /* Data accessible to all tasks */
 
 
-#define CURR_SHARED_MAGIC 0x3a6025edU
+#define CURR_SHARED_MAGIC 0xc590e67eU
 
 #define USER_VERSION   1
 
@@ -51,7 +51,7 @@ class shared_info
   mtinfo mt;
   loadavginfo loadavg;
   LONG pid_src;
-  char prefer_forkable_hardlinks; /* single byte access always is atomic */
+  char forkable_hardlink_support; /* single byte access always is atomic */
 
   void initialize ();
   void init_obcaseinsensitive ();



More information about the Cygwin-cvs mailing list