loadlibrary() unsafe ?

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

loadlibrary() unsafe ?

fredvs
Hello.

Here the thing: a open-source program, eSpeak (voice synthezer) uses 2 libraries: espeak-library and portaudio.

In eSpeak source =>

- For the Windows version, the libraries are included in the executable (static linked).
  To do run the program => it is easy => just run the executable via TProcess (espeak.exe).

- For Linux, the eSpeak source produces a executable with static espeak-library included but without static portaudio-library included in executable.
  So portaudio library must be installed in library path of the system.
  If portaudio is not installed in library path of the system, a trick that works is:

  To do run the program =>
  - first dynamic load portaudio with loadlibrary('/the_path_you_want/libportaudio.so').
  - run the executable via TProcess (espeak).

- For freeBSD, the eSpeak source produces a executable without static espeak-library nor static portaudio-library included in executable.
  So both espeak-library and portaudio-library must be installed in library path of the system.
  If libraries are not installed in library path of the system, a trick that works is:

  To do run the program =>
  - first dynamic load portaudio with loadlibrary('/the_path_you_want/libportaudio.so').
  - then dynamic load libespeak with loadlibrary('/the_path_you_want/libespeak.so').
  - run the executable via TProcess (speak).

All is working like charms.

Now i heard that this trick is unsafe.

Why ?

Many thanks.

Fre;D
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

Mark Morgan Lloyd-5
fredvs wrote:

> - For [...], the eSpeak source produces a executable without static
> espeak-library nor static portaudio-library included in executable.
>   So both espeak-library and portaudio-library must be installed in library
> path of the system.
>   If libraries are not installed in library path of the system, a trick that
> works is:
>
>   To do run the program =>
>   - first dynamic load portaudio with
> loadlibrary('/the_path_you_want/libportaudio.so').
>   - then dynamic load libespeak with
> loadlibrary('/the_path_you_want/libespeak.so').
>   - run the executable via TProcess (speak).
>
> All is working like charms.
>
> Now i heard that this trick is unsafe.
>
> Why ?

I suspect that the point is that whatever reference counts that the OS
maintains for the library will be decremented if the outer program
terminates, at which point the demand-loaded code will be removed from
memory.

Before trying anything like this, I suggest that it would be worth
finding under what circumstances appropriate symlinks etc. are set up.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

Ewald-2
In reply to this post by fredvs
On 06/10/2015 01:20 PM, fredvs wrote:
>   To do run the program =>
>   - first dynamic load portaudio with
> loadlibrary('/the_path_you_want/libportaudio.so').
>   - run the executable via TProcess (espeak).

I must admit this is a creative way of solving this particular issue :-)
I wonder if you have tried to set the environment variable
`LD_LIBRARY_PATH` to contain `the_path_you_want` before you spawn the
other process?

See also
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html :
section 3.3.

--
Ewald

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
@ Ewald and Mark => thanks for answer. ;-)

Yep, i agree, the process is "exotic" but works so good.

I have to agree too, following Martin Schreiber way: => export LD_PRELOAD=$LIBPORTAUDIO, before to run the executable works too.

And is maybe safer.
And do not need dynlibs in uses section.
And no need to unloadlib().

So, in short, use loadlibrary() to pre-load a library works but better not use it ;-)

Many thanks.

Fre;D



Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

Mark Morgan Lloyd-5
fredvs wrote:

> @ Ewald and Mark => thanks for answer. ;-)
>
> Yep, i agree, the process is "exotic" but works so good.
>
> I have to agree too, following Martin Schreiber way: => export
> LD_PRELOAD=$LIBPORTAUDIO, before to run the executable works too.
>
> And is maybe safer.
> And do not need dynlibs in uses section.
> And no need to unloadlib().
>
> So, in short, use loadlibrary() to pre-load a library works but better not
> use it ;-)

The best way would be to first find out what package in the OS installs
the symlink or files you need, and to document this as a prerequisite.

The next-best way would be to investigate whether the wrapper can set
LD_LIBRARY_PATH and export this to the loaded program.

The next-next-best way would be LD_PRELOAD, since this potentially has
path issues of its own.

After that comes the way you first thought of :-)

For problems like this,  man ld.so  is your friend.

--
Mark Morgan Lloyd
markMLl .AT. telemetry.co .DOT. uk

[Opinions above are the author's, not those of his employers or colleagues]
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
In reply to this post by Ewald-2
Hello.

Sorry to come back with that story... ;-(

I have used inside a script LD_LIBRARY_PATH` and at end runs the espeak executable.

So a Tprocess run the script.

Ok, it works but... now i do not have access to espeak anymore, not possible to cancel the speech.

AProcess.terminate has impact on the script but not on what has done by the script.

So, the loadlibrary() approach is more efficient because the process runs espeak directly => so possible to cancel it...

Does it really have problems to use that loadlibrary()  approach ?

Ok maybe first a process that run a script for assign path of lib and then a other process to run espeak ?

Many thanks.

Fre;D





Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

Ewald-2
On 06/20/2015 09:05 AM, fredvs wrote:
> Hello.
>
> Sorry to come back with that story... ;-(
>
> I have used inside a script LD_LIBRARY_PATH` and at end runs the espeak
> executable.
>
> So a Tprocess run the script.
Why use a script? When you exec(), a parameter is available to set the
environment variables[1]. Using a TProcess, try setting the
`Environment` property before running it[2].

Hope it helps :-)

[1] http://linux.die.net/man/3/exec
[2]
http://www.freepascal.org/docs-html/fcl/process/tprocess.environment.html

--
Ewald

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
@ Ewald => many thanks for your help.

Your advices are very promising...

I will test it and write later the result.

Write you soon.

Fre;D
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
In reply to this post by Ewald-2
Re_hello.

Huh, i am loosed...

Here the working script run by TProcess (but that cannot be canceled)=>
________________________________________________
#!/bin/sh
LIBPORTAUDIO=libportaudio.so  #portaudio library
ESPEAKBIN=espeak                 #espeak binary
CALLDIR=${0%/*}/                    # directory where is ESPEAKBIN
export LD_PRELOAD=$CALLDIR$LIBPORTAUDIO
$CALLDIR/$ESPEAKBIN
_______________________________________________

Now, i try to do the same with TProcess.environment =>

 - AProcess.Environment.Text := 'export LD_PRELOAD=/home/fred/sak/sak/sakit/liblinux64/libportaudio.so'  ;  
=> do not work ;-(

 - AProcess.Environment.Text := 'LD_LIBRARY_PATH=/home/fred/sak/sak/sakit/liblinux64/'  ;  
=> do not work too ;-(

Is the way how i use AProcess.Environment ok ?
Maybe i did something wrong while using environment...

Thanks.

Fre;D


 
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
Re-re-re-Hello.

This one does not work too ;-( =>
- AProcess.Environment.Text := 'LD_PRELOAD=/home/fred/sak/sak/sakit/liblinux64/libportaudio.so'  ;  

???

Many thanks.

Fre;D
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

Giuliano Colla
Il 20/06/2015 17:11, fredvs ha scritto:
> Re-re-re-Hello.
>
> This one does not work too ;-( =>
> - AProcess.Environment.Text :=
> 'LD_PRELOAD=/home/fred/sak/sak/sakit/liblinux64/libportaudio.so'  ;
>
> ???
>
> Many thanks.
Have you tried:
AProcess.Environment.Text :=
LD_LIBRARY_PATH=/home/fred/sak/sak/sakit/liblinux64/
?
Once supplied the right folder, this should be sufficient to make the
loader search the proper file.

Giuliano

--
Giuliano Colla

Project planning question: when it's 90% done, are we halfway or not yet?

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
@ Giuliano => thanks for advice ;-)

Hum, finally, using =>
AProcess.Environment.Text := 'LD_PRELOAD=/home/fred/sak/sak/sakit/liblinux64/libportaudio_x64.so'  ;  

It works ;-) ( was a  wrong character...)

So, many, many thanks, i get the solution.

Many thanks to everybody.

Fre;D
Many thanks ;-)
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

wkitty42
In reply to this post by fredvs
On 06/20/2015 11:11 AM, fredvs wrote:
> Re-re-re-Hello.
>
> This one does not work too ;-( =>
> - AProcess.Environment.Text :=
> 'LD_PRELOAD=/home/fred/sak/sak/sakit/liblinux64/libportaudio.so'  ;

how many "sak" are there really? you have two plus "sakit"... this is the first
you've posted anything of your directory structure... perhaps you can modify
your script to echo the data so you can compare it?

________________________________________________
#!/bin/sh
LIBPORTAUDIO=libportaudio.so  #portaudio library
ESPEAKBIN=espeak                 #espeak binary
CALLDIR=${0%/*}/                    # directory where is ESPEAKBIN
echo "export LD_PRELOAD=$CALLDIR$LIBPORTAUDIO"
export LD_PRELOAD=$CALLDIR$LIBPORTAUDIO
echo "$CALLDIR/$ESPEAKBIN"
$CALLDIR/$ESPEAKBIN
_______________________________________________

note the two echo lines i added... you should be able to see or retrieve them to
see/know the live data so you can make your direct attempts work with the same...

--
  NOTE: No off-list assistance is given without prior approval.
        *Please keep mailing list traffic on the list* unless
        private contact is specifically requested and granted.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: loadlibrary() unsafe ?

fredvs
@ Waldo => thanks for help. ;-)

But TProcess.Environment kills the script...
No script needed anymore ;-)
The script will become a program.ini...

=> Works perfectly.
TProcess.Environment.Text := 'LD_PRELOAD='/the/directory/of/thelibrary.so'  ;  

=> And now, canclel_speech (= TProcess.terminate) woks perfectly (not with a script).

Fre;D

PS: Excellent tip to know, many thanks for the gem.
Many thanks ;-)