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

Hello Monks,

I have used Perl threading in quite a few scripts, but I'm banging my head against a wall with this issue. What happens is, the output gets mangled up and breaks the Bash term (which I then need to reset in many cases). The lock is indeed working (as far as keeping multiple threads from printing out at once). I have narrowed down the problem to the ssh/tcpdump line. Without this line, I can output anything and there are no issues. With this line, I can literally print anything after the lock and the output will get mangled up 50% of the time. Specifically, the output appears to indent further every line. If I print entire packets every packet line is further indented. After the script is done running the Bash term is all screwed up, sometimes newlines don't process, and sometimes the text is invisible.

use threads; use threads::shared; my $lock:shared; foreach my $server (@servers) { chomp $server; push (@threads, threads->create (\&dumpServer, $server)); } foreach (@threads) { $_->join(); } sub dumpServer { my $server = shift; my $net = `ssh -tt $server '/usr/local/bin/tcpdump -c10 -nntttt port + 80 2>/dev/null' 2>/dev/null`; ## This is the line that causes the i +ssue lock($lock); print "TEST - $server\n"; ## Want to print $net output here, but pr +inting even a simple string gives me the issue }
Example Output:
TEST - Server1 TEST - Server2 TEST - Server3 TEST - Server4 Bash Prompt (now need to reset term)
Thanks for your time.

Replies are listed 'Best First'.
Re: Threads Printing Issue - Output Mangled / Term Crashing
by BrowserUk (Patriarch) on Apr 14, 2014 at 09:24 UTC

    You appear to be outputting linefeeds but not carriage returns.

    Fix that and your problem will go away.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thanks for the reply Browser. I understand what you're saying, but these results don't make sense to me.

      I can simply print "TEST\n" on that line and it will still have the output formatting issue. I use this type of print in many scripts, and have never seen it destroy the terminal or mangle output. Since I'm using Linux, why is a carriage return required?

      Also, the issue only presents itself when the SSH/tcpdump line is included. The results of that line are currently put into a variable which isn't even being printed out.

      Thanks

        Since I'm using Linux, why is a carriage return required?

        (Note: most of this is guesswork regarding *nix -- not my FOE -- but its nothing to do with threads)

        In the days of old, the linefeed character just moved to the next line; an carriage return was required to move to the start of the line. (Think about how manual typewriters operate. If you ever seen one.)

        To the best of my knowledge, most *nix consoles only require LF to cause them to perform both operations, but that's a reinterpretation of the purpose, and probably only operates when the console is operating in 'cooked' mode.

        My guess is that

        the issue only presents itself when the SSH/tcpdump line is included.

        the command you are issuing is switching the terminal into 'raw' (or 'ultra-raw') mode and failing to reset it when it ends. Hence, thereafter, the LF is only moving to the next line, and is failing to return to the left hand edge.

        Perhaps the thing to do is use Term::ReadKey::ReadMode() to control/restore the settings after the command ends.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        compare stty Settings before and after. Probably something with opost, ocrnl, or some such Parameter.
Re: Threads Printing Issue - Output Mangled / Term Crashing
by salva (Canon) on Apr 14, 2014 at 11:41 UTC
    Probably the error is related to having several ssh processes accessing /dev/tty in parallel.

    In any case, you can try using Net::OpenSSH::Parallel.

      Well I have a lot of other scripts that create many simultaneous SSH connections at once (with no issues like this, even printing out data, etc). However, this is the first time I've had to use the SSH -tt option to force Force pseudo-tty allocation on the remote systems. This is because tcpdump doesn't die after the SSH connection is closed without it (at least until it sees a packet that matches the filter).
        Then, and easy workaround is to write a wrapper for tcpdump that launches it and then kills it when stdin is closed:
        #!/usr/bin/perl # untested: require POSIX; my $pid = fork; unless ($pid) { exec 'tcpdump', @ARGV; POSIX::_exit(1); } while (<>) { ; }; # just discard input until EOF kill KILL => $pid;
        You will have to place the wrapper on the remote machines (or just make it into a perl one-liner and pass it on the ssh call)
Re: Threads Printing Issue - Output Mangled / Term Crashing
by Preceptor (Deacon) on Apr 15, 2014 at 20:27 UTC

    It's a problem that I haven't run into, despite doing something similar. Without wanting to contradict the excellent advice thus far, my suggestion would be to create an 'IO' thread - feed it via a Queue, and have it simply handle serialising the input/output operations. Which is especially significant when doing file writes, but I'd imagine similar problems are applicable, since you've still got buffering to contend with.

      Yeah I really need to become familiar with Queue. So far I've done everything with locks, but sooner or later...