Re: [PATCH 1/4] dlopen: switch to new pathfinder class

2016-09-01 Thread Michael Haubenwallner
On 08/31/2016 09:12 PM, Corinna Vinschen wrote:
> Hi Michael,
> 
> On Aug 31 20:07, Michael Haubenwallner wrote:
>> Instead of find_exec, without changing behaviour use new pathfinder
>> class with new allocator_interface around tmp_pathbuf and new vstrlist
>> class.
>> * pathfinder.h (pathfinder): New file.
>> * vstrlist.h (allocator_interface, allocated_type, vstrlist): New file.
>> * dlfcn.cc (dlopen): Avoid redundant GetModuleHandleExW with RTLD_NOLOAD
>> and RTLD_NODELETE.  Switch to new pathfinder class, using
>> (tmp_pathbuf_allocator): New class.
>> (get_full_path_of_dll): Drop.
>> [...]
> 
> Just one nit here:
> 
>> +/* Dumb allocator using memory from tmp_pathbuf.w_get ().
>> +
>> +   Does not reuse free'd memory areas.  Instead, memory
>> +   is released when the tmp_pathbuf goes out of scope.
>> +
>> +   ATTENTION: Requesting memory from an instance of tmp_pathbuf breaks
>> +   when another instance on a newer stack frame has provided memory. */
>> +class tmp_pathbuf_allocator
>> +  : public allocator_interface
> 
> You didn't reply to
> https://cygwin.com/ml/cygwin-developers/2016-08/msg00013.html
> So, again, why didn't you simply integrate a tmp_pathbuf member into the
> pathfinder class, rather than having to create some additional allocator
> class?  I'm probably not the most diligent C++ hacker, but to me this
> additional allocator is a bit confusing.

Sorry, seems I've failed to fully grasp your concerns firsthand in
https://cygwin.com/ml/cygwin-developers/2016-08/msg00016.html
Second try to answer:
https://cygwin.com/ml/cygwin-developers/2016-09/msg0.html

> The rest of the patch looks good.  I'll look further into the patchset
> later tomorrow.

Thanks!
/haubi/



Re: [PATCH 3/4] dlopen: on x/lib search x/bin if exe is in x/bin

2016-09-01 Thread Corinna Vinschen
Hi Michael,

On Aug 31 20:07, Michael Haubenwallner wrote:
> citing https://cygwin.com/ml/cygwin-developers/2016-08/msg00020.html
> > Consider the file /usr/bin/cygz.dll:
> > - dlopen (libz.so)success
> > - dlopen (/usr/bin/libz.so)   success
> > - dlopen (/usr/lib/libz.so)   fails
> 
> * dlfcn.c (dlopen): For dlopen("x/lib/N"), when the application
> executable is in "x/bin/", search for "x/bin/N" before "x/lib/N".
> ---
>  winsup/cygwin/dlfcn.cc | 36 +++-
>  1 file changed, 35 insertions(+), 1 deletion(-)
> 
> diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
> index e592512..f8b8743 100644
> --- a/winsup/cygwin/dlfcn.cc
> +++ b/winsup/cygwin/dlfcn.cc
> @@ -153,6 +153,25 @@ collect_basenames (pathfinder::basenamelist & basenames,
>basenames.appendv (basename, baselen, ext, extlen, NULL);
>  }
>  
> +/* Identify dir of current executable into exedirbuf using wpathbuf buffer.
> +   Return length of exedirbuf on success, or zero on error. */
> +static int
> +get_exedir (char * exedirbuf, wchar_t * wpathbuf)
> +{
> +  /* Unless we have a special cygwin loader, there is no such thing like
> + DT_RUNPATH on Windows we can use to search for dlls, except for the
> + directory of the main executable. */
> +  GetModuleFileNameW (NULL, wpathbuf, NT_MAX_PATH);
> +  wchar_t * lastwsep = wcsrchr (wpathbuf, L'\\');
> +  if (!lastwsep)
> +return 0;
> +  *lastwsep = L'\0';
> +  *exedirbuf = '\0';
> +  if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, wpathbuf, exedirbuf, 
> NT_MAX_PATH))
> +return 0;
> +  return strlen (exedirbuf);
> +}

You could just use the global variable program_invocation_name.  If in
doubt, use the Windows path global_progname and convert it to full POSIX
via cygwin_conv_path.

>  extern "C" void *
>  dlopen (const char *name, int flags)
>  {
> @@ -184,13 +203,28 @@ dlopen (const char *name, int flags)
>/* handle for the named library */
>path_conv real_filename;
>wchar_t *wpath = tp.w_get ();
> +  char *cpath = tp.c_get ();
>  
>pathfinder finder (allocator, basenames); /* eats basenames */
>  
>if (have_dir)
>   {
> +   int dirlen = basename - 1 - name;
> +
> +   /* if the specified dir is x/lib, and the current executable
> +  dir is x/bin, do the /lib -> /bin mapping, which is the
> +  same actually as adding the executable dir */
> +   if (dirlen >= 4 && !strncmp (name + dirlen - 4, "/lib", 4))
> + {
> +   int exedirlen = get_exedir (cpath, wpath);
> +   if (exedirlen == dirlen &&
> +   !strncmp (cpath, name, dirlen - 4) &&
> +   !strcmp (cpath + dirlen - 4, "/bin"))
> + finder.add_searchdir (cpath, exedirlen);
> + }
> +
> /* search the specified dir */
> -   finder.add_searchdir (name, basename - 1 - name);
> +   finder.add_searchdir (name, dirlen);
>   }
>else
>   {
> -- 
> 2.7.3

Rest looks ok.


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: [PATCH 1/4] dlopen: switch to new pathfinder class

2016-09-01 Thread Corinna Vinschen
On Sep  1 13:05, Michael Haubenwallner wrote:
> On 08/31/2016 09:12 PM, Corinna Vinschen wrote:
> > Hi Michael,
> > 
> > On Aug 31 20:07, Michael Haubenwallner wrote:
> >> Instead of find_exec, without changing behaviour use new pathfinder
> >> class with new allocator_interface around tmp_pathbuf and new vstrlist
> >> class.
> >> * pathfinder.h (pathfinder): New file.
> >> * vstrlist.h (allocator_interface, allocated_type, vstrlist): New file.
> >> * dlfcn.cc (dlopen): Avoid redundant GetModuleHandleExW with RTLD_NOLOAD
> >> and RTLD_NODELETE.  Switch to new pathfinder class, using
> >> (tmp_pathbuf_allocator): New class.
> >> (get_full_path_of_dll): Drop.
> >> [...]
> > 
> > Just one nit here:
> > 
> >> +/* Dumb allocator using memory from tmp_pathbuf.w_get ().
> >> +
> >> +   Does not reuse free'd memory areas.  Instead, memory
> >> +   is released when the tmp_pathbuf goes out of scope.
> >> +
> >> +   ATTENTION: Requesting memory from an instance of tmp_pathbuf breaks
> >> +   when another instance on a newer stack frame has provided memory. */
> >> +class tmp_pathbuf_allocator
> >> +  : public allocator_interface
> > 
> > You didn't reply to
> > https://cygwin.com/ml/cygwin-developers/2016-08/msg00013.html
> > So, again, why didn't you simply integrate a tmp_pathbuf member into the
> > pathfinder class, rather than having to create some additional allocator
> > class?  I'm probably not the most diligent C++ hacker, but to me this
> > additional allocator is a bit confusing.
> 
> Sorry, seems I've failed to fully grasp your concerns firsthand in
> https://cygwin.com/ml/cygwin-developers/2016-08/msg00016.html
> Second try to answer:
> https://cygwin.com/ml/cygwin-developers/2016-09/msg0.html

Ok, I see what you mean, but it doesn't make me really happy.

I'm willing to take it for now but I'd rather see basenames being a
member of pathfinder right from the start, so you just instantiate
finder and call methods on it.  Given that basenames is a member,
you can do the allocator stuff completely inside the pathfinder class.


Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: [PATCH 2/4] dlopen (pathfinder): try each basename per dir

2016-09-01 Thread Corinna Vinschen
On Aug 31 20:07, Michael Haubenwallner wrote:
> Rather than searching all search dirs per one basename,
> search for all basenames within per one search dir.
> 
> pathfinder.h (check_path_access): Interchange dir- and basename-loops.
> ---
>  winsup/cygwin/pathfinder.h | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/winsup/cygwin/pathfinder.h b/winsup/cygwin/pathfinder.h
> index bbba168..c306604 100644
> --- a/winsup/cygwin/pathfinder.h
> +++ b/winsup/cygwin/pathfinder.h
> @@ -182,12 +182,12 @@ public:
>basenamelist::member const ** found_basename = NULL)
>{
>  char const * critname = criterion.name ();
> -for (basenamelist::iterator name = basenames_.begin ();
> -  name != basenames_.end ();
> -  ++name)
> -  for (searchdirlist::iterator dir(searchdirs_.begin ());
> -dir != searchdirs_.end ();
> -++dir)
> +for (searchdirlist::iterator dir(searchdirs_.begin ());
> +  dir != searchdirs_.end ();
> +  ++dir)
> +  for (basenamelist::iterator name = basenames_.begin ();
> +name != basenames_.end ();
> +++name)
>   if (criterion.test (dir, name))
> {
>   debug_printf ("(%s), take %s%s", critname,
> -- 
> 2.7.3

This one's fine, of course.


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: [PATCH 4/4] dlopen: on unspecified lib dir search exe dir

2016-09-01 Thread Corinna Vinschen
On Aug 31 20:07, Michael Haubenwallner wrote:
> Applications installed to some prefix like /opt/application do expect
> dlopen("libAPP.so") to load "/opt/application/bin/cygAPP.dll", which
> is similar to "/opt/application/lib/libAPP.so" on Linux.
> 
> See also https://cygwin.com/ml/cygwin-developers/2016-08/msg00020.html
> 
> * dlfcn.cc (dlopen): For dlopen("N"), search directory where the
> application executable is in.
> ---
>  winsup/cygwin/dlfcn.cc | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/winsup/cygwin/dlfcn.cc b/winsup/cygwin/dlfcn.cc
> index f8b8743..974092e 100644
> --- a/winsup/cygwin/dlfcn.cc
> +++ b/winsup/cygwin/dlfcn.cc
> @@ -232,6 +232,12 @@ dlopen (const char *name, int flags)
>not use the LD_LIBRARY_PATH environment variable. */
> finder.add_envsearchpath ("LD_LIBRARY_PATH");
>  
> +   /* Search the current executable's directory like
> +  the Windows loader does for linked dlls. */
> +   int exedirlen = get_exedir (cpath, wpath);
> +   if (exedirlen)
> + finder.add_searchdir (cpath, exedirlen);
> +
> /* Finally we better have some fallback. */
> finder.add_searchdir ("/usr/bin", 8);
> finder.add_searchdir ("/usr/lib", 8);
> -- 
> 2.7.3

Still not quite sure if that's the right thing to do...


Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature