(sorry about previous empty mail) Hi Corinna,
This is a fixup for the race condition where multiple processes failed to concurrently create identical hardlinks. So I'm quite successful with the forkable hardlinks now... /haubi/ On 03/30/2016 08:53 PM, Michael Haubenwallner wrote: > 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. > > * dll_init.h (struct dll): Declare member variables fbi, fii, > forkable_ntname. Declare methods nominate_forkable, > create_forkable. Define inline method forkedntname. > (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. > Declare public method cleanup_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. > * forkable.cc: Implement static functions mkdirs, rmdirs, > rmdirs_synchronized, read_fii, read_fbi, format_IndexNumber, > rootname, sidname, exename, lwtimename. Define static array > forkable_nameparts. > (struct dll): Implement nominate_forkable, create_forkable. > (struct dll_list): Implement forkable_ntnamesize, > prepare_forkables_nomination, update_forkables_needs, > update_forkables, create_forkables, close_mutex, > cleanup_forkables, try_remove_forkables, denominate_forkables. > (dll_list::set_forkables_inheritance): Also for forkables_mutex. > (dll_list::request_forkables): Use new methods to create the > hardlinks as necessary. > (dll_list::release_forkables): When hardlink creation turned out > to be impossible, close all the related handles and free the > distinct memory. > * 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. > --- > winsup/cygwin/dll_init.cc | 28 +- > winsup/cygwin/dll_init.h | 33 ++ > winsup/cygwin/forkable.cc | 1036 > +++++++++++++++++++++++++++++++++++++++++++++ > winsup/cygwin/pinfo.cc | 3 + > winsup/cygwin/syscalls.cc | 24 +- > 5 files changed, 1115 insertions(+), 9 deletions(-)
>From 7a824877dbfe2aee0437378a52b8946000a38cbe Mon Sep 17 00:00:00 2001 From: Michael Haubenwallner <[email protected]> Date: Fri, 11 Nov 2016 14:29:21 +0100 Subject: [PATCH] forkables: fix creating dirs and .local file in parallel --- winsup/cygwin/forkable.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/winsup/cygwin/forkable.cc b/winsup/cygwin/forkable.cc index 0a8a528..b712834 100644 --- a/winsup/cygwin/forkable.cc +++ b/winsup/cygwin/forkable.cc @@ -65,14 +65,14 @@ mkdirs (PWCHAR ntdirname, int lastsepcount) IO_STATUS_BLOCK iosb; status = NtCreateFile (&dh, GENERIC_READ | SYNCHRONIZE, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ, - FILE_OPEN_IF, /* allow concurrency */ + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (NT_SUCCESS(status)) NtClose (dh); - else + else if (status != STATUS_OBJECT_NAME_COLLISION) /* already exists */ success = false; debug_printf ("%y = NtCreateFile (%p, dir %W)", status, dh, ntdirname); } @@ -806,14 +806,14 @@ dll_list::create_forkables () IO_STATUS_BLOCK iosb; status = NtCreateFile (&hlocal, GENERIC_WRITE | SYNCHRONIZE, &oa, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, - FILE_SHARE_READ, - FILE_OPEN_IF, /* allow concurrency */ + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (NT_SUCCESS (status)) CloseHandle (hlocal); - else + else if (status != STATUS_OBJECT_NAME_COLLISION) /* already exists */ success = false; debug_printf ("%y = NtCreateFile (%p, %W)", status, hlocal, ntname); } @@ -874,7 +874,10 @@ rmdirs_synchronized (WCHAR ntbuf[NT_MAX_PATH], int depth, int maxdepth, if (mutex) { if (lasterror != ERROR_ALREADY_EXISTS) - rmdirs (ntbuf); + { + debug_printf ("cleaning up for mutex %W", mutexname); + rmdirs (ntbuf); + } BOOL bret = CloseHandle (mutex); debug_printf ("%d = CloseHandle (%p, %W): %E", bret, mutex, mutexname); -- 2.8.3
