2000-02-18 03:38:33 +08:00
|
|
|
/* dll_init.h
|
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
struct per_module
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2017-11-27 21:36:06 +08:00
|
|
|
#ifdef __i386__
|
2000-07-15 10:48:11 +08:00
|
|
|
char ***envptr;
|
2013-04-23 17:44:36 +08:00
|
|
|
#endif
|
2000-07-15 10:48:11 +08:00
|
|
|
void (**ctors)(void);
|
|
|
|
void (**dtors)(void);
|
|
|
|
void *data_start;
|
|
|
|
void *data_end;
|
|
|
|
void *bss_start;
|
|
|
|
void *bss_end;
|
|
|
|
int (*main)(int, char **, char **);
|
|
|
|
per_module &operator = (per_process *p)
|
|
|
|
{
|
2017-11-27 21:36:06 +08:00
|
|
|
#ifdef __i386__
|
2000-07-15 10:48:11 +08:00
|
|
|
envptr = p->envptr;
|
2013-04-23 17:44:36 +08:00
|
|
|
#endif
|
2000-07-15 10:48:11 +08:00
|
|
|
ctors = p->ctors;
|
|
|
|
dtors = p->dtors;
|
|
|
|
data_start = p->data_start;
|
|
|
|
data_end = p->data_end;
|
|
|
|
bss_start = p->bss_start;
|
|
|
|
bss_end = p->bss_end;
|
|
|
|
main = p->main;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
void run_ctors ();
|
|
|
|
void run_dtors ();
|
2000-02-18 03:38:33 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
typedef enum
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2000-07-15 10:48:11 +08:00
|
|
|
DLL_NONE,
|
2016-12-07 18:58:26 +08:00
|
|
|
DLL_SELF, /* main-program.exe, cygwin1.dll */
|
2000-07-15 10:48:11 +08:00
|
|
|
DLL_LINK,
|
|
|
|
DLL_LOAD,
|
|
|
|
DLL_ANY
|
|
|
|
} dll_type;
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
struct dll
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2000-07-15 10:48:11 +08:00
|
|
|
struct dll *next, *prev;
|
|
|
|
per_module p;
|
|
|
|
HMODULE handle;
|
|
|
|
int count;
|
2009-08-22 05:32:06 +08:00
|
|
|
bool has_dtors;
|
2000-07-15 10:48:11 +08:00
|
|
|
dll_type type;
|
2011-05-30 14:52:12 +08:00
|
|
|
long ndeps;
|
|
|
|
dll** deps;
|
2011-05-29 04:55:34 +08:00
|
|
|
DWORD image_size;
|
2011-05-31 00:09:29 +08:00
|
|
|
void* preferred_base;
|
2012-02-09 22:41:21 +08:00
|
|
|
PWCHAR modname;
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
FILE_INTERNAL_INFORMATION fii;
|
|
|
|
PWCHAR forkable_ntname;
|
2016-12-07 18:58:25 +08:00
|
|
|
WCHAR ntname[1]; /* must be the last data member */
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
void detach ();
|
|
|
|
int init ();
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
void nominate_forkable (PCWCHAR);
|
|
|
|
bool create_forkable ();
|
2009-08-22 05:32:06 +08:00
|
|
|
void run_dtors ()
|
|
|
|
{
|
|
|
|
if (has_dtors)
|
|
|
|
{
|
|
|
|
has_dtors = 0;
|
|
|
|
p.run_dtors ();
|
|
|
|
}
|
|
|
|
}
|
forkables: On fork failure, retry with hardlinks.
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
2016-12-07 18:58:28 +08:00
|
|
|
PWCHAR forkedntname ()
|
|
|
|
{
|
|
|
|
return forkable_ntname && *forkable_ntname ? forkable_ntname : ntname;
|
|
|
|
}
|
2000-02-18 03:38:33 +08:00
|
|
|
};
|
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
#define MAX_DLL_BEFORE_INIT 100
|
2000-02-18 03:38:33 +08:00
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
class dll_list
|
2000-02-18 03:38:33 +08:00
|
|
|
{
|
2017-03-03 00:26:53 +08:00
|
|
|
bool forkables_supported ()
|
|
|
|
{
|
|
|
|
return cygwin_shared->forkable_hardlink_support >= 0;
|
|
|
|
}
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
DWORD forkables_dirx_size;
|
2017-03-01 17:19:37 +08:00
|
|
|
bool forkables_created;
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
PWCHAR forkables_dirx_ntname;
|
|
|
|
PWCHAR forkables_mutex_name;
|
|
|
|
HANDLE forkables_mutex;
|
2016-12-07 18:58:26 +08:00
|
|
|
void track_self ();
|
forkables: On fork failure, retry with hardlinks.
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
2016-12-07 18:58:28 +08:00
|
|
|
dll *find_by_forkedntname (PCWCHAR ntname);
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
size_t forkable_ntnamesize (dll_type, PCWCHAR fullntname, PCWCHAR modname);
|
|
|
|
void prepare_forkables_nomination ();
|
|
|
|
void update_forkables_needs ();
|
|
|
|
bool update_forkables ();
|
|
|
|
bool create_forkables ();
|
|
|
|
void denominate_forkables ();
|
|
|
|
bool close_mutex ();
|
|
|
|
void try_remove_forkables (PWCHAR dirbuf, size_t dirlen, size_t dirbufsize);
|
|
|
|
void set_forkables_inheritance (bool);
|
|
|
|
void request_forkables ();
|
2016-12-07 18:58:26 +08:00
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
dll *end;
|
|
|
|
dll *hold;
|
|
|
|
dll_type hold_type;
|
2011-04-21 08:53:55 +08:00
|
|
|
static muto protect;
|
2016-12-07 18:58:25 +08:00
|
|
|
/* Use this buffer under loader lock conditions only. */
|
|
|
|
static WCHAR NO_COPY nt_max_path_buffer[NT_MAX_PATH];
|
2000-02-18 03:38:33 +08:00
|
|
|
public:
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
static HANDLE ntopenfile (PCWCHAR ntname, NTSTATUS *pstatus = NULL,
|
|
|
|
ULONG openopts = 0, ACCESS_MASK access = 0,
|
|
|
|
HANDLE rootDir = NULL);
|
|
|
|
static bool read_fii (HANDLE fh, PFILE_INTERNAL_INFORMATION pfii);
|
|
|
|
static bool read_fbi (HANDLE fh, PFILE_BASIC_INFORMATION pfbi);
|
2016-12-07 18:58:25 +08:00
|
|
|
static PWCHAR form_ntname (PWCHAR ntbuf, size_t bufsize, PCWCHAR name);
|
|
|
|
static PWCHAR form_shortname (PWCHAR shortbuf, size_t bufsize, PCWCHAR name);
|
|
|
|
static PWCHAR nt_max_path_buf ()
|
|
|
|
{
|
|
|
|
return nt_max_path_buffer;
|
|
|
|
}
|
|
|
|
static PCWCHAR buffered_shortname (PCWCHAR name)
|
|
|
|
{
|
|
|
|
form_shortname (nt_max_path_buffer, NT_MAX_PATH, name);
|
|
|
|
return nt_max_path_buffer;
|
|
|
|
}
|
|
|
|
|
2016-12-07 18:58:26 +08:00
|
|
|
dll *main_executable;
|
2000-07-15 10:48:11 +08:00
|
|
|
dll start;
|
|
|
|
int loaded_dlls;
|
|
|
|
int reload_on_fork;
|
2016-12-07 18:58:25 +08:00
|
|
|
dll *operator [] (PCWCHAR ntname);
|
2000-07-15 10:48:11 +08:00
|
|
|
dll *alloc (HINSTANCE, per_process *, dll_type);
|
2010-02-02 10:00:01 +08:00
|
|
|
dll *find (void *);
|
2002-11-14 12:29:39 +08:00
|
|
|
void detach (void *);
|
2000-07-15 10:48:11 +08:00
|
|
|
void init ();
|
2009-06-08 11:53:40 +08:00
|
|
|
void load_after_fork (HANDLE);
|
2011-05-31 00:09:29 +08:00
|
|
|
void reserve_space ();
|
|
|
|
void load_after_fork_impl (HANDLE, dll* which, int retries);
|
2016-12-07 18:58:25 +08:00
|
|
|
dll *find_by_modname (PCWCHAR modname);
|
2011-05-30 14:52:12 +08:00
|
|
|
void populate_deps (dll* d);
|
|
|
|
void topsort ();
|
|
|
|
void topsort_visit (dll* d, bool goto_tail);
|
|
|
|
void append (dll* d);
|
2011-06-06 13:02:13 +08:00
|
|
|
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
void release_forkables ();
|
|
|
|
void cleanup_forkables ();
|
|
|
|
bool setup_forkables (bool with_forkables)
|
|
|
|
{
|
2017-03-01 17:19:37 +08:00
|
|
|
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. */
|
forkables: Create forkable hardlinks, yet unused.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
2016-12-07 18:58:27 +08:00
|
|
|
with_forkables = true;
|
|
|
|
if (with_forkables)
|
|
|
|
request_forkables ();
|
|
|
|
return with_forkables;
|
|
|
|
}
|
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
dll *inext ()
|
|
|
|
{
|
|
|
|
while ((hold = hold->next))
|
|
|
|
if (hold_type == DLL_ANY || hold->type == hold_type)
|
|
|
|
break;
|
|
|
|
return hold;
|
|
|
|
}
|
2011-04-21 08:53:55 +08:00
|
|
|
|
2001-11-03 11:32:27 +08:00
|
|
|
dll *istart (dll_type t)
|
|
|
|
{
|
|
|
|
hold_type = t;
|
|
|
|
hold = &start;
|
|
|
|
return inext ();
|
|
|
|
}
|
2011-04-21 08:53:55 +08:00
|
|
|
void guard(bool lockit)
|
|
|
|
{
|
|
|
|
if (lockit)
|
|
|
|
protect.acquire ();
|
|
|
|
else
|
|
|
|
protect.release ();
|
|
|
|
}
|
2008-08-04 23:55:32 +08:00
|
|
|
friend void dll_global_dtors ();
|
2011-04-21 08:53:55 +08:00
|
|
|
dll_list () { protect.init ("dll_list"); }
|
2000-02-18 03:38:33 +08:00
|
|
|
};
|
|
|
|
|
2011-05-29 04:55:34 +08:00
|
|
|
/* References:
|
|
|
|
http://msdn.microsoft.com/en-us/windows/hardware/gg463125
|
|
|
|
http://msdn.microsoft.com/en-us/library/ms809762.aspx
|
|
|
|
*/
|
|
|
|
struct pefile
|
|
|
|
{
|
|
|
|
IMAGE_DOS_HEADER dos_hdr;
|
|
|
|
|
2013-04-23 17:44:36 +08:00
|
|
|
char* rva (ptrdiff_t offset) { return (char*) this + offset; }
|
|
|
|
PIMAGE_NT_HEADERS pe_hdr () { return (PIMAGE_NT_HEADERS) rva (dos_hdr.e_lfanew); }
|
|
|
|
PIMAGE_OPTIONAL_HEADER optional_hdr () { return &pe_hdr ()->OptionalHeader; }
|
2011-05-29 04:55:34 +08:00
|
|
|
PIMAGE_DATA_DIRECTORY idata_dir (DWORD which)
|
|
|
|
{
|
2013-04-23 17:44:36 +08:00
|
|
|
PIMAGE_OPTIONAL_HEADER oh = optional_hdr ();
|
2011-05-29 04:55:34 +08:00
|
|
|
return (which < oh->NumberOfRvaAndSizes)? oh->DataDirectory + which : 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2000-07-15 10:48:11 +08:00
|
|
|
extern dll_list dlls;
|
2005-04-15 01:34:03 +08:00
|
|
|
void dll_global_dtors ();
|
2010-02-02 10:00:01 +08:00
|
|
|
|
|
|
|
/* These probably belong in a newlib header but we can keep them here
|
|
|
|
for now. */
|
|
|
|
extern "C" int __cxa_atexit(void (*)(void*), void*, void*);
|
|
|
|
extern "C" int __cxa_finalize(void*);
|