ovedpo15 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!
I'm facing a strange bug. Please consider the following code:
print("Before setting command: $path\n"); $cmd = "ldd $path"; print("Before running command\n"); ($stdout, $stderr, $exit_status) = capture { system($cmd); }; print("After running command\n");
The output:
Before setting command: /proc/self/fd/1 Before running command
And it gets stuck. It continues running only after I click Ctrl+C. Then it will resume and continue running my script. The output looks like:
Before setting command: /proc/self/fd/1 Before running command ^CAfter running command
Note the ^C. Any other path works well.
Now the strange part. If I run ldd /proc/self/fd/1 in the command line - it does not get stuck and it works (just prints: ldd: /proc/self/fd/1: not regular file). And also, if I change the code to be:
print("Before setting command: $path\n"); $cmd = "$LDD $path"; print("Before running command\n"); $stdout = `$cmd`; #($stdout, $stderr, $exit_status) = capture { system($cmd); }; print("After running command\n");
Then I get:
Before setting command: /proc/self/fd/1 Before running command ldd: /proc/self/fd/1: not regular file After running command
Which makes me believe that Capture::Tiny getting stuck on this path.
Why does it happen? How should it be handled? If I could check if the path is dynamic, then I could just ignore this path. The question is, could it happen on other paths as well?

Replies are listed 'Best First'.
Re: Capture::Tiny getting stuck on ldd /proc/self/fd/1
by shmem (Chancellor) on Jun 21, 2021 at 21:58 UTC
    Before setting command: /proc/self/fd/1 Before running command

    Why are you running ldd on STDOUT of your script? /proc/self pertains to the running process, the numbers 0, 1, 2 in the fd directory are STDIN, STDOUT and STDERR. These are not executables.

    The standard file handles are redirected by Capture::Tiny. I have not looked deeply at what happens, but ldd tries to read from a file handle which doesn't deliver anything, and capture can't read since ldd doesn't deliver. Smells of deadlock. The Ctrl-C cancels the program invoked by capture, and the program continues.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      Hi!
      Thank you for your explanation. It makes sense. I'm running ldd on a list of paths I find to find the shared libs. Is there a way in perl to check if path is dynamic, before actually running ldd. Something like:
      if (-dy $path) { # Run ldd of path }
      where -dy checks if $path is dynamic. If it's not built in, is there a libraries or another way to do so?
        I'm running ldd on a list of paths I find to find the shared libs.

        There are no shared libs in /proc. If you find any in /dev, chances are that you were hacked.

        Is there a way in perl to check if path is dynamic

        You could use the linux file(1) utility to check the type and look for shared object and dynamically linked in its output. I'm not aware of a perl module which provides that information.

        You didn't answer the question: for what purpose? If you just want the dynamic libraries your system knows about, run ldconfig -p and parse the output. Note that most of the files it reports are symbolic links, which you might have to resolve, depending on purpose.

        perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
Re: Capture::Tiny getting stuck on ldd /proc/self/fd/1
by Anonymous Monk on Jun 22, 2021 at 15:27 UTC
    /proc, /dev, and /sys on a Linux machine are all "fake filesystems" – they are actually kernel APIs and should not be "searched."
      /dev is a regular directory and should not be "searched" is BS