perltie

Why does underscore in path name make Perl script hang?


I'm troubleshooting a Perl script that unexpectedly hanging when it never hung before. I don't know Perl. I finally traced the problem to a file path string. This code works:

$eng_morph = "~/datafile.en.db";
tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664|| die "Cannot open dbmfile $eng_morph";

When I change the file name to include an underscore, the second line hangs forever:

$eng_morph = "~/datafile.en_us.db";
tie %eng_morph, "DB_File", $eng_morph, O_CREAT|O_RDWR, 0664|| die "Cannot open dbmfile $eng_morph";

Is there something wrong with the syntax? Is there any way to allow the underscores?

I'm using Ubuntu 14.04. Here's the uname output:

Linux asus-notebook 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

Also, I'm also using the default Perl in the distro. Its version output is:

This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi (with 41 registered patches, see perl -V for more detail)


Solution

  • This problem was intermittent. It turned out to be a threading problem -- as many intermittent problems are. The clue was the presence of an odd file in the output folder: "~/_db_datafile.en.db" ... or any defined output file name prefixed with "~/_db_". This output file ranged from 0 to 14K bytes when the desired output file should have been 2 or 3 megabytes. It looked like the Perl tie() function was interrupted while creating the DB file.

    The code in question was being called from a Python script that used non-blocking threads with subprocess.Popen() piping. The Python script spawned the Perl script and continued its flow. While the Perl script was still creating the DB file, Python's non-blocked thread started piping data. This stopped the Perl script's file creation and caused a lockup.

    The underscore in the file name was only the first intermittent instance of this error, and ultimately irrelevant to the problem.

    Resolution was to simply create a while not os.path.exists(eng_morph): loop in the Python code to pause until the proper DB file exists.