From: Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
To: cygwin-developers@cygwin.com
Cc: Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
Subject: [PATCH 2/6] dll_list: Track main executable and cygwin1.dll.
Date: Wed, 07 Dec 2016 11:00:00 -0000 [thread overview]
Message-ID: <1481108310-14825-3-git-send-email-michael.haubenwallner@ssi-schaefer.com> (raw)
In-Reply-To: <1481108310-14825-1-git-send-email-michael.haubenwallner@ssi-schaefer.com>
Even for the main executable and cygwin1.dll store the file name as full
NT path. Create the child process using the main executable's file name
converted from the full NT path stored before.
* dll_init.cc (dll_list::alloc): Search for DLL_SELF type entry
with module name like for DLL_LINK, use full NT path to search
for DLL_LOAD type only. For DLL_SELF type do not indicate
having a destructor to be called.
(dll_list::find): Ignore DLL_SELF type entries.
(dll_list::init): Ditto. Call track_self method.
(dll_list::track_self): New.
(dll_list::load_after_fork): Call track_self method.
* dll_init.h (enum dll_type): Add DLL_SELF, for the main
executable and cygwin1.dll.
(struct dll_list): Declare private method track_self. Declare
member variable main_executable.
* fork.cc (frok::parent): Use ntname from dlls.main_executable
to create child process, converted to short path using
dll_list::buffered_shortname.
---
winsup/cygwin/dll_init.cc | 26 ++++++++++++++++++++------
winsup/cygwin/dll_init.h | 4 ++++
winsup/cygwin/fork.cc | 15 ++++++++++++---
3 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 6bdd437..8c208d5 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -307,8 +307,9 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
guard (true);
/* Already loaded? For linked DLLs, only compare the basenames. Linked
DLLs are loaded using just the basename and the default DLL search path.
- The Windows loader picks up the first one it finds. */
- dll *d = (type == DLL_LINK) ? dlls.find_by_modname (modname) : dlls[ntname];
+ The Windows loader picks up the first one it finds.
+ This also applies to cygwin1.dll and the main-executable (DLL_SELF). */
+ dll *d = (type != DLL_LOAD) ? dlls.find_by_modname (modname) : dlls[ntname];
if (d)
{
if (!in_forkee)
@@ -344,7 +345,8 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
wcscpy (d->ntname, ntname);
d->modname = d->ntname + (modname - ntname);
d->handle = h;
- d->has_dtors = true;
+ /* DLL_SELF dtors (main-executable, cygwin1.dll) are run elsewhere */
+ d->has_dtors = type != DLL_SELF;
d->p = p;
d->ndeps = 0;
d->deps = NULL;
@@ -488,7 +490,7 @@ dll_list::find (void *retaddr)
dll *d = &start;
while ((d = d->next))
- if (d->handle == h)
+ if (d->type != DLL_SELF && d->handle == h)
break;
return d;
}
@@ -533,11 +535,22 @@ dll_list::detach (void *retaddr)
void
dll_list::init ()
{
+ track_self ();
+
/* Walk the dll chain, initializing each dll */
dll *d = &start;
dll_global_dtors_recorded = d->next != NULL;
while ((d = d->next))
- d->init ();
+ if (d->type != DLL_SELF) /* linked and early loaded dlls */
+ d->init ();
+}
+
+void
+dll_list::track_self ()
+{
+ /* for cygwin1.dll and main-executable: maintain hardlinks only */
+ alloc (cygwin_hmodule, user_data, DLL_SELF);
+ main_executable = alloc (GetModuleHandle (NULL), user_data, DLL_SELF);
}
#define A64K (64 * 1024)
@@ -604,7 +617,7 @@ dll_list::reserve_space ()
/* Reload DLLs after a fork. Iterates over the list of dynamically loaded
DLLs and attempts to load them in the same place as they were loaded in the
- parent. */
+ parent. Updates main-executable and cygwin1.dll tracking. */
void
dll_list::load_after_fork (HANDLE parent)
{
@@ -614,6 +627,7 @@ dll_list::load_after_fork (HANDLE parent)
in_load_after_fork = true;
if (reload_on_fork)
load_after_fork_impl (parent, dlls.istart (DLL_LOAD), 0);
+ track_self ();
in_load_after_fork = false;
}
diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h
index e85fdb1..a132adb 100644
--- a/winsup/cygwin/dll_init.h
+++ b/winsup/cygwin/dll_init.h
@@ -40,6 +40,7 @@ struct per_module
typedef enum
{
DLL_NONE,
+ DLL_SELF, /* main-program.exe, cygwin1.dll */
DLL_LINK,
DLL_LOAD,
DLL_ANY
@@ -75,6 +76,8 @@ struct dll
class dll_list
{
+ void track_self ();
+
dll *end;
dll *hold;
dll_type hold_type;
@@ -94,6 +97,7 @@ public:
return nt_max_path_buffer;
}
+ dll *main_executable;
dll start;
int loaded_dlls;
int reload_on_fork;
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 86689b4..45c571b 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -181,7 +181,7 @@ frok::child (volatile char * volatile here)
if (fixup_shms_after_fork ())
api_fatal ("recreate_shm areas after fork failed");
- /* load dynamic dlls, if any */
+ /* load dynamic dlls, if any, re-track main-executable and cygwin1.dll */
dlls.load_after_fork (hParent);
cygheap->fdtab.fixup_after_fork (hParent);
@@ -345,11 +345,20 @@ frok::parent (volatile char * volatile stack_here)
while (1)
{
+ PCWCHAR forking_progname = NULL;
+ if (dlls.main_executable)
+ forking_progname = dll_list::buffered_shortname
+ (dlls.main_executable->ntname);
+ if (!forking_progname || !*forking_progname)
+ forking_progname = myself->progname;
+
syscall_printf ("CreateProcessW (%W, %W, 0, 0, 1, %y, 0, 0, %p, %p)",
- myself->progname, myself->progname, c_flags, &si, &pi);
+ forking_progname, myself->progname, c_flags, &si, &pi);
hchild = NULL;
- rc = CreateProcessW (myself->progname, /* image to run */
+ /* cygwin1.dll may reuse the forking_progname buffer, even
+ in case of failure: don't reuse forking_progname later */
+ rc = CreateProcessW (forking_progname, /* image to run */
GetCommandLineW (), /* Take same space for command
line as in parent to make
sure child stack is allocated
--
2.7.3
next prev parent reply other threads:[~2016-12-07 11:00 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-07 10:59 RFC: [PATCH 0/6] When fork fails, retry with hardlinks Michael Haubenwallner
2016-12-07 10:59 ` [PATCH 6/6] forkables: Document hardlink creation at forktime Michael Haubenwallner
2016-12-07 11:00 ` [PATCH 5/6] forkables: Keep hardlinks disabled via shared mem Michael Haubenwallner
2016-12-07 11:00 ` Michael Haubenwallner [this message]
2016-12-07 11:02 ` [PATCH 1/6] dll_list: Store dll file name as full NT path Michael Haubenwallner
2016-12-07 11:02 ` [PATCH 4/6] forkables: On fork failure, retry with hardlinks Michael Haubenwallner
2016-12-07 11:14 ` [PATCH 3/6] forkables: Create forkable hardlinks, yet unused Michael Haubenwallner
2016-12-08 15:51 ` RFC: [PATCH 0/6] When fork fails, retry with hardlinks Corinna Vinschen
2017-01-09 17:45 ` Michael Haubenwallner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1481108310-14825-3-git-send-email-michael.haubenwallner@ssi-schaefer.com \
--to=michael.haubenwallner@ssi-schaefer.com \
--cc=cygwin-developers@cygwin.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).