Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3323738
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 17, 20262026-05-17T23:20:17+00:00 2026-05-17T23:20:17+00:00

How can I test that resource (file based cache for caching output of a

  • 0

How can I test that resource (file based cache for caching output of a webapp in Perl) behaves sanely under concurrent access to said shared resource?

I wrote a simple file-based cache, written in Perl, which uses locking to serialize write access, i.e. to have only one process that (re)generates cache entry. This cache is to be used for caching output of Perl webapp (gitweb), if it matters.

I’d like to test that said cache behaves sanely under concurrent access, for example that only one process would run subroutine used to generate cache ($cache->compute($key, sub { ... })), that all processes would get generated data, that if process writing to cache entry dies it wouldn’t deadlock processes waiting for cache to be (re)generated etc.

How should I do it? Is there a ready Perl module that I can use?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-17T23:20:18+00:00Added an answer on May 17, 2026 at 11:20 pm

    In the end I based my work on Unix for Perl programmers: pipes and processes by Aaron Crane; though in those notes he simplified things to not deal with reading from multiple processes without locking (in those notes temporary file is used for second stream).

    The code uses only Test::More and no non-core Perl modules

    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    use POSIX qw(dup2);
    use Fcntl qw(:DEFAULT);
    use IO::Handle;
    use IO::Select;
    use IO::Pipe;
    
    use Test::More;
    
    # [...]
    
    # from http://aaroncrane.co.uk/talks/pipes_and_processes/
    sub fork_child (&) {
        my ($child_process_code) = @_;
    
        my $pid = fork();
        die "Failed to fork: $!\n" if !defined $pid;
    
        return $pid if $pid != 0;
    
        # Now we're in the new child process
        $child_process_code->();
        exit;
    }
    
    sub parallel_run (&) {
        my $child_code = shift;
        my $nchildren = 2;
    
        my %children;
        my (%pid_for_child, %fd_for_child);
        my $sel = IO::Select->new();
        foreach my $child_idx (1..$nchildren) {
            my $pipe = IO::Pipe->new()
                or die "Failed to create pipe: $!\n";
    
            my $pid = fork_child {
                $pipe->writer()
                    or die "$$: Child \$pipe->writer(): $!\n";
                dup2(fileno($pipe), fileno(STDOUT))
                    or die "$$: Child $child_idx failed to reopen stdout to pipe: $!\n";
                close $pipe
                    or die "$$: Child $child_idx failed to close pipe: $!\n";
    
                # From Test-Simple-0.96/t/subtest/fork.t
                #
                # Force all T::B output into the pipe (redirected to STDOUT),
                # for the parent builder as well as the current subtest builder.
                {
                    no warnings 'redefine';
                    *Test::Builder::output         = sub { *STDOUT };
                    *Test::Builder::failure_output = sub { *STDOUT };
                    *Test::Builder::todo_output    = sub { *STDOUT };
                }
    
                $child_code->();
    
                *STDOUT->flush();
                close(STDOUT);
            };
    
            $pid_for_child{$pid} = $child_idx;
            $pipe->reader()
                or die "Failed to \$pipe->reader(): $!\n";
            $fd_for_child{$pipe} = $child_idx;
            $sel->add($pipe);
    
            $children{$child_idx} = {
                'pid'    => $pid,
                'stdout' => $pipe,
                'output' => '',
            };
        }
    
        while (my @ready = $sel->can_read()) {
            foreach my $fh (@ready) {
                my $buf = '';
                my $nread = sysread($fh, $buf, 1024);
    
                exists $fd_for_child{$fh}
                    or die "Cannot find child for fd: $fh\n";
    
                if ($nread > 0) {
                    $children{$fd_for_child{$fh}}{'output'} .= $buf;
                } else {
                    $sel->remove($fh);
                }
            }
        }
    
        while (%pid_for_child) {
            my $pid = waitpid -1, 0;
            warn "Child $pid_for_child{$pid} ($pid) failed with status: $?\n"
                if $? != 0;
            delete $pid_for_child{$pid};
        }
    
        return map { $children{$_}{'output'} } keys %children;
    }
    
    # [...]
    
    @output = parallel_run {
        my $data = $cache->compute($key, \&get_value_slow);
        print $data;
    };
    is_deeply(
        \@output,
        [ ($value) x 2 ],
        'valid data returned by both process'
    );
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

We have some methods that call File.Copy, File.Delete, File.Exists, etc. How can we test
It is my understanding that I can test that a method call will occur
Using Java, how can I test that a URL is contactable, and returns a
How can I use JUnit idiomatically to test that some code throws an exception?
This might be an interesting question. I need to test that if I can
How can I test my site in AOL without installing AOL? I did that
In ActionScript, how can you test if an object is defined, that is, not
If unit-test names can become outdated over time and if you consider that the
Is there a good test suite or tool set that can automate website navigation
I am trying to test a proof of concept that I can run a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.