Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of jjore (6662)

Tuesday August 04, 2009
07:17 PM

Life... draining... out..., ruby-1.8 to blame

Losing...

the will to live...

must...

have...

useful stack traces...

I wish Ruby were as useful as Perl. I wish the following had the arguments like I'd get from any perl program using Carp. I also wish this code had just used perror(3) so it'd report the ordinary message "Address already in use" instead of making up its own message "no acceptor."

>> Thin web server (v1.2.2 codename I Find Your Lack of Sauce Disturbing)
>> Maximum connections set to 1024
>> Listening on 127.0.0.1:8859, CTRL+C to stop
Failed to start the service
RuntimeError
no acceptor
/usr/lib/ruby/gems/1.8/gems/eventmachine-0.12.8/lib/eventmachine.rb:56 5:in `start_tcp_server'
/usr/lib/ruby/gems/1.8/gems/eventmachine-0.12.8/lib/eventmac hine.rb:565:in `start_server'
/usr/lib/ruby/gems/1.8/gems/thin-1.2.2/lib/thin/backends/tcp_ser ver.rb:16:in `connect'
/usr/lib/ruby/gems/1.8/gems/thin-1.2.2/lib/thin/backends/base.rb:49:i n `start'
/usr/lib/ruby/gems/1.8/gems/eventmachine-0.12.8/lib/eventmachine.rb:242 :in `call'
/usr/lib/ruby/gems/1.8/gems/eventmachine-0.12.8/lib/eventmachine.rb:242: in `run_machine'
/usr/lib/ruby/gems/1.8/gems/eventmachine-0.12.8/lib/eventmachine. rb:242:in `run'
/usr/lib/ruby/gems/1.8/gems/thin-1.2.2/lib/thin/backends/base.rb:57:in `start'
/usr/lib/ruby/gems/1.8/gems/thin-1.2.2/lib/thin/server.rb:156:in `start'
/usr/lib/ruby/gems/1.8/gems/thin-1.2.2/lib/thin/controllers/controller. rb:80:in `start'
./basic.rb:68
./basic.rb:51:in `initialize'
./basic.rb:51:in `new'
./basic.rb:51

Sunday August 02, 2009
11:37 PM

My phone knows perl

It's cool to run perl on my phone. I tried compiling bleadperl on it just now but it didn't generate a Makefile. I guess I'm going to learn how the configuration system works now. The last few weeks have been endless yak shaving. I tracked down some debuild problem through diff to FSF's diffutils and all their various versions, learned how to override parts of Makefiles for ExtUtils::MakeMaker, installed and set up Gnus, have been getting into the internals of Git in a fairly serious way.

Blech. It seems it's so difficult to get to /actual/ work.

http://www.webos-internals.org/wiki/Application:Terminal fwiw

Sunday July 26, 2009
04:20 AM

Your future Unicode overlords

Recently while testing perl-5.10.1-RC0 at $work I found that it worked seamlessly for everything except our custom debianized build. It turns out http://cpansearch.perl.org/src/ADAMK/Parse-CPAN-Meta-1.39/t/data/utf_16_le_bom.y ml a UTF-16LE encoded file with a BOM (byte order mark) breaks my build of a .deb including this.

debuild makes both the binary and source packages. It's nice for presenting the whole picture to someone trying to follow along later. debuild uses dpkg-source to generate a diff between the vendor's source package and the source tree used in the actual debian build. dpkg-source uses your diff which probably comes from diffutils-2.8.1 which was the last release in 2002 (http://ftp.gnu.org/pub/gnu/diffutils/).

It looks like dev continued on til 2008 including the dev releases (ftp://alpha.gnu.org/pub/gnu/diffutils/, http://git.savannah.gnu.org/cgit/diffutils.git). Somewhere along the way it got support for multibyte characters. It still doesn't work for that UTF-16LE text file with a BOM.

Oh well. Anyway, consider this a tale of basic tools just not working nicely when your source code is in Unicode.

Friday July 24, 2009
03:34 PM

You'll miss composable functions

In perl or almost any other functional language (I guess) you can combine functions together and the innards of one thing aren't going to affect the flow control of the other. Here's a simple bit of perl:

method trap (CodeRef $block) {
    $block->() }
    uffda(); # Called in Perl, not called in Ruby
}
 
method moo ( ... ) {
    trap( sub {
 
        # Early return because ...
        return ... if ...;
 
        ...
    } );
}

Writing the equivalent flow control in Ruby and I found out today that the return() calls go all the way through and past the wrapping "trap" function.

WTF? I don't think I understand how Ruby programmers put up with this. Maybe 1.9 is better about this.

Thursday July 23, 2009
07:09 PM

Gems driving me to drink

I don't know my blood pressure but I'm considering getting a desk-side monitor just to empirically know when I'm being driven out of my mind.

I wish:

Work day's done now. I feel ill.

03:12 PM

Cuneiform version numbers

I was disappointed yesterday to find out I couldn't fully use Sumerian numbers even though I don't know a thing about them. Given the ASCII program:

use 5.010_000;
use strict;
use warnings;
use version qw( qv );
use Devel::Peek qw( Dump );
use charnames qw( :full );
 
binmode STDOUT, ':encoding(utf8)';
eval "use utf8;
    package Booga;
    our \$VERSION = '\N{CUNEIFORM NUMERIC SIGN TWO ASH}';
    \$INC{'Booga.pm'} = 1;
    sub iz { 'Okay!' }
 
    1;
"
  or die $@;
 
eval "use utf8;
    use Booga \N{CUNEIFORM NUMERIC SIGN THREE ASH};
    print Booga::iz(), qq{\\n};
    1;
"
  or die $@;
 
Dump( $Booga::VERSION > 1);
Dump( Booga->VERSION );
Dump( qv( $Booga::VERSION ) );

Several things came out:

  • "\N{CUNEIFORM NUMERIC SIGN TWO ASH}"
       

    •        
    • is numeric according to /\p{Nd}/
             
    • is not numeric according to <=>
             
    • is not numeric according to version::qv
             
    • is not numeric according to Booga->VERSION
         
  • use Booga &#x12409;

    Bareword "&#x12409;" not allowed while "strict subs" in use at (eval 7) line 2.

  • use Booga 2;

    Version string '&#x12409;' contains invalid data; ignoring: '&#x12409;' at (eval 7) line 2.
    Booga version 2 required--this is only version 0 at (eval 7) line 2.

  • $Booga::VERSION > 2

    Argument "\x{12409}" isn't numeric in numeric gt (&gt;) at booga line 27.

  • Booga->VERSION

    Version string '&#x12409;' contains invalid data; ignoring: '&#x12409;' at booga line 28.
     
    SV = PV(0x82ca18) at 0x847b30
      REFCNT = 1
      FLAGS = (POK,pPOK)
      PV = 0x25beb0 "0"\0
      CUR = 1
      LEN = 16

Also, the HTML formatting of this post is defeating me. :-(

Wednesday July 22, 2009
05:02 PM

git up to date

One of my esteemed prior co-workers recommends that I follow git releases very closely. I've added a "git-update" command into my path so I can just say "git update" occasionally to get all the newest features and bugs.

#!/bin/bash
(
  set -e
  cd $HOME/src/git
  export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
  git fetch
  git clean -xdf
  git reset --hard
  git merge origin/master
  make configure
  sh configure --prefix=/opt/git
  make all doc
  sudo make install install-doc install-html
)

03:47 PM

A MANIFESTly bad idea

While cleaning my home directory, I found this beauty in ~/OhNo-0.01/MANIFEST.

touch $'\x2f'|
Changes
Makefile.PL
MANIFEST
README
lib/OhNo.pm

Monday July 20, 2009
10:48 AM

Add remote debugging terminal to mod_perl

Occasionally my mod_perl servers go sour and it's useful to attach a remote debugger. There's typically no useful console and production doesn't run under the debugger. I'm forced into two things: force load the debugger with Enbugger and then have it connect to a remote terminal.

Works great BTW and is almost identical to http://use.perl.org/~jjore/journal/39319. The only real difference is we're eval()ing something different. This is also documented as a "cookbook" recipe in at http://search.cpan.org/dist/Enbugger.

Step 1: Start a remote terminal. I like netcat. I'll just start a Terminal and have it listen on port 8000. Anything that connect there will show up and I'll be able to type to it, etc.

nc -l 8000

Step 2: Attach GDB to mod_perl. Assuming my process ID is 765, I can attach with the simple command:

gdb -p 765

It's occasionally useful to know if there's anything "interesting" going on so get a quick backtrace of the current call stack:

(gdb) backtrace
#0  0xb7f7b919 in poll () from /lib/tls/libc.so.6
#1  0xb7da57ff in apr_poll () from /opt/apache/das/lib/libapr-0.so.0
#2  0x080b2050 in child_main ()
#3  0x080b231e in make_child ()
#4  0x080b2393 in startup_children ()
#5  0x080b279c in ap_mpm_run ()
#6  0x080b93c9 in main ()

Step 3: As in http://use.perl.org/~jjore/journal/39319, I need to know whether there's a thread context to pass into eval().

(gdb) print $thread_context = (void*)Perl_get_context()
$1 = (void *) 0x0

OR

(gdb) print $thread_context = (void*)Perl_get_context()
$1 = (void *) 0x800000

Step 4: Install the debugger. If you've got a $thread_context, it goes before the eval string (eval_pv($ctx,"...",0)).

(gdb) call (void*)Perl_eval_pv("eval { require Enbugger; print STDERR qq{stopping\\n}; $ENV{PERLDB_OPTS} = 'RemotePort=localhost:4000'; Enbugger->stop;}; print STDERR $@; print STDERR qq{stopped?\\n};", 0)

Step 5: profit:

jjore$ nc -l -p 4000
 
Loading DB routines from perl5db.pl version 1.28
Editor support available.
 
Enter h or `h h' for help, or `man perldebug' for more help.
 
x
main::((eval 982):1):    print STDERR $@
  DB<1> 0  0
  DB<1>

Step 6: Now detach to resume your program. You've interrupted your program at two levels. First at perl, so run "c" to continue out from the perl debugger. Second, in gdb so "detach" or "quit" to continue the process.

12:05 AM

Get a stack trace from your running perl

When you've got a process that's spinning and don't know what's going on, it's useful to get a perl level stack trace. There's a "simple" gdb function to get your perl to write its call stack to STDERR. It's not entirely without risk to corrupting your process. I've used it just fine against my mod_perl in prod when all our other normal methods of inspection failed.

Step 1: attach with gdb.

jjore$ ps -x
  PID   TT  STAT      TIME COMMAND
...
  765 s001  S      0:00.01 perl -e while(1){sleep 1}
 
jjore$ gdb --quiet -p 765
Attaching to process 780.
Reading symbols for shared libraries . done
Reading symbols for shared libraries
warning: Could not find object file "..." - no debug information available for "...c".
...
..... done
0x9005e46e in __semwait_signal ()
(gdb)

Step 2: Get a C level backtrace to see if that's informative enough. In this case, I can see the program is current in some sleep functions. In prod, I've seen things like bugs in libxslt show up nicely here - I could see the stack extending down into the libxml/libxslt libraries which eventually lead me to solve the problem by upgrade my libxml library.

(gdb) bt
#0  0x9005e46e in __semwait_signal ()
#1  0x9005e2ef in nanosleep$UNIX2003 ()
#2  0x900b3e71 in sleep$UNIX2003 ()
#3  0x0015a054 in Perl_pp_sleep ()
#4  0x00081bb7 in Perl_runops_debug ()
#5  0x000b6791 in perl_run ()
#6  0x0000247e in main ()

Step 3: Get your thread context pointer. For threaded perl, you'll need to pass in a thread context pointer. If this step returns 0x0, you don't have threaded perl and shouldn't pass this argument in. If you get something other than 0x0, you'll need to use this value.

(gdb) print $thread_context = (void*)Perl_get_context()
$1 = (void *) 0x0

OR

(gdb) print $thread_context = (void*)Perl_get_context()
$1 = (void *) 0x800000

Step 4: Use Carp::cluck() from inside gdb. If you've got a $thread_context, use it.

(gdb) call (void*)Perl_eval_pv($thread_context, "require Carp;Carp::cluck('Hi')", 0)

OR

(gdb) call (void*)Perl_eval_pv("require Carp; Carp::cluck('Hi')", 0)

Step 5: Profit.

Hi at (eval 1) line 1
    eval 'require Carp; Carp::cluck(\'Hi\')
;' called at -e line 1