mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-22 00:38:06 +08:00
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.
This commit is contained in:
parent
8bbb3d3a23
commit
135577f708
@ -87,17 +87,9 @@ struct dll
|
|||||||
class dll_list
|
class dll_list
|
||||||
{
|
{
|
||||||
/* forkables */
|
/* forkables */
|
||||||
enum
|
bool forkables_supported ();
|
||||||
{
|
|
||||||
forkables_unknown,
|
|
||||||
forkables_impossible,
|
|
||||||
forkables_disabled,
|
|
||||||
forkables_needless,
|
|
||||||
forkables_needed,
|
|
||||||
forkables_created,
|
|
||||||
}
|
|
||||||
forkables_needs;
|
|
||||||
DWORD forkables_dirx_size;
|
DWORD forkables_dirx_size;
|
||||||
|
bool forkables_created;
|
||||||
PWCHAR forkables_dirx_ntname;
|
PWCHAR forkables_dirx_ntname;
|
||||||
PWCHAR forkables_mutex_name;
|
PWCHAR forkables_mutex_name;
|
||||||
HANDLE forkables_mutex;
|
HANDLE forkables_mutex;
|
||||||
@ -160,10 +152,11 @@ public:
|
|||||||
void cleanup_forkables ();
|
void cleanup_forkables ();
|
||||||
bool setup_forkables (bool with_forkables)
|
bool setup_forkables (bool with_forkables)
|
||||||
{
|
{
|
||||||
if (forkables_needs == forkables_impossible)
|
if (!forkables_supported ())
|
||||||
return true; /* short cut to not retry fork */
|
return true; /* no need to retry fork */
|
||||||
/* Once used, always use forkables in current process chain. */
|
if (forkables_created)
|
||||||
if (forkables_needs != forkables_unknown)
|
/* Once created, use forkables in current
|
||||||
|
process chain on first fork try already. */
|
||||||
with_forkables = true;
|
with_forkables = true;
|
||||||
if (with_forkables)
|
if (with_forkables)
|
||||||
request_forkables ();
|
request_forkables ();
|
||||||
|
@ -501,17 +501,56 @@ dll::create_forkable ()
|
|||||||
return false;
|
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 */
|
/* return the number of characters necessary to store one forkable name */
|
||||||
size_t
|
size_t
|
||||||
dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modname)
|
dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modname)
|
||||||
{
|
{
|
||||||
/* per process, this is the first forkables-method ever called */
|
/* per process, this is the first forkables-method ever called */
|
||||||
if (forkables_needs == forkables_unknown &&
|
if (cygwin_shared->forkable_hardlink_support == 0) /* Unknown */
|
||||||
!cygwin_shared->prefer_forkable_hardlinks)
|
{
|
||||||
forkables_needs = forkables_impossible; /* short cut */
|
/* 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)
|
UNICODE_STRING fn;
|
||||||
return 0;
|
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)
|
if (!forkables_dirx_size)
|
||||||
{
|
{
|
||||||
@ -560,9 +599,6 @@ dll_list::forkable_ntnamesize (dll_type type, PCWCHAR fullntname, PCWCHAR modnam
|
|||||||
void
|
void
|
||||||
dll_list::prepare_forkables_nomination ()
|
dll_list::prepare_forkables_nomination ()
|
||||||
{
|
{
|
||||||
if (!forkables_dirx_ntname)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dll *d = &dlls.start;
|
dll *d = &dlls.start;
|
||||||
while ((d = d->next))
|
while ((d = d->next))
|
||||||
stat_real_file_once (d); /* uses nt_max_path_buf () */
|
stat_real_file_once (d); /* uses nt_max_path_buf () */
|
||||||
@ -627,106 +663,19 @@ dll_list::prepare_forkables_nomination ()
|
|||||||
void
|
void
|
||||||
dll_list::update_forkables_needs ()
|
dll_list::update_forkables_needs ()
|
||||||
{
|
{
|
||||||
dll *d;
|
if (forkables_created)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
/* already have created hardlinks in this process, ... */
|
/* already have created hardlinks in this process, ... */
|
||||||
forkables_needs = forkables_needless;
|
dll *d = &start;
|
||||||
d = &start;
|
|
||||||
while ((d = d->next) != NULL)
|
while ((d = d->next) != NULL)
|
||||||
if (d->forkable_ntname && !*d->forkable_ntname)
|
if (d->forkable_ntname && !*d->forkable_ntname)
|
||||||
{
|
{
|
||||||
/* ... but another dll was loaded since last fork */
|
/* ... but another dll was loaded since last fork */
|
||||||
debug_printf ("needed, since last fork loaded %W", d->ntname);
|
debug_printf ("needed, since last fork loaded %W", d->ntname);
|
||||||
forkables_needs = forkables_needed;
|
forkables_created = false;
|
||||||
break;
|
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,
|
/* Create the nominated forkable hardlinks and directories as necessary,
|
||||||
@ -958,7 +907,7 @@ dll_list::close_mutex ()
|
|||||||
void
|
void
|
||||||
dll_list::cleanup_forkables ()
|
dll_list::cleanup_forkables ()
|
||||||
{
|
{
|
||||||
if (!forkables_dirx_ntname)
|
if (!forkables_supported ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool locked = close_mutex ();
|
bool locked = close_mutex ();
|
||||||
@ -1034,58 +983,32 @@ dll_list::set_forkables_inheritance (bool inherit)
|
|||||||
void
|
void
|
||||||
dll_list::request_forkables ()
|
dll_list::request_forkables ()
|
||||||
{
|
{
|
||||||
if (!forkables_dirx_ntname)
|
if (!forkables_supported ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Even on forkables_impossible, keep the number of open handles
|
|
||||||
stable across the fork, and close them when releasing only. */
|
|
||||||
prepare_forkables_nomination ();
|
prepare_forkables_nomination ();
|
||||||
|
|
||||||
update_forkables_needs ();
|
update_forkables_needs ();
|
||||||
|
|
||||||
set_forkables_inheritance (true);
|
set_forkables_inheritance (true);
|
||||||
|
|
||||||
if (forkables_needs == forkables_disabled)
|
if (forkables_created)
|
||||||
{
|
return; /* nothing new to create */
|
||||||
/* 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;
|
|
||||||
|
|
||||||
dll *d = &start;
|
dll *d = &start;
|
||||||
while ((d = d->next))
|
while ((d = d->next))
|
||||||
d->nominate_forkable (forkables_dirx_ntname);
|
d->nominate_forkable (forkables_dirx_ntname);
|
||||||
|
|
||||||
bool updated = update_forkables ();
|
if (update_forkables ())
|
||||||
|
forkables_created = true;
|
||||||
if (!updated)
|
|
||||||
forkables_needs = forkables_needless;
|
|
||||||
else
|
|
||||||
forkables_needs = forkables_created;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
dll_list::release_forkables ()
|
dll_list::release_forkables ()
|
||||||
{
|
{
|
||||||
if (!forkables_dirx_ntname)
|
if (!forkables_supported ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
set_forkables_inheritance (false);
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -518,7 +518,7 @@ details. */
|
|||||||
regions. It is incremented when incompatible changes are made to the shared
|
regions. It is incremented when incompatible changes are made to the shared
|
||||||
memory region *or* to any named shared mutexes, semaphores, etc. */
|
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
|
/* 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
|
names include the CYGWIN_VERSION_SHARED_DATA version as well as this
|
||||||
|
@ -334,6 +334,7 @@ shared_info::initialize ()
|
|||||||
NtAllocateLocallyUniqueId (&luid);/* Initialize pid_src to a low */
|
NtAllocateLocallyUniqueId (&luid);/* Initialize pid_src to a low */
|
||||||
InterlockedExchange (&pid_src, /* random value to make start pid */
|
InterlockedExchange (&pid_src, /* random value to make start pid */
|
||||||
luid.LowPart % 2048);/* less predictably */
|
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
|
/* Defer debug output printing the installation root and installation key
|
||||||
up to this point. Debug output except for system_printf requires
|
up to this point. Debug output except for system_printf requires
|
||||||
the global shared memory to exist. */
|
the global shared memory to exist. */
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
/* Data accessible to all tasks */
|
/* Data accessible to all tasks */
|
||||||
|
|
||||||
|
|
||||||
#define CURR_SHARED_MAGIC 0x3a6025edU
|
#define CURR_SHARED_MAGIC 0xc590e67eU
|
||||||
|
|
||||||
#define USER_VERSION 1
|
#define USER_VERSION 1
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class shared_info
|
|||||||
mtinfo mt;
|
mtinfo mt;
|
||||||
loadavginfo loadavg;
|
loadavginfo loadavg;
|
||||||
LONG pid_src;
|
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 initialize ();
|
||||||
void init_obcaseinsensitive ();
|
void init_obcaseinsensitive ();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user