Skip to content

Fix AnyEvent socket EOF and interpreter callback recursion #1118

Description

@fglock

Summary

Restore AnyEvent::HTTPD 0.93 compatibility by fixing two independently reproducible PerlOnJava runtime defects:

  1. The JVM backend does not deliver socket EOF promptly after the HTTP server disconnects.
  2. The interpreter backend aborts with StackOverflowError while executing AnyEvent condition-variable callbacks.

The distribution is pure Perl. These should be reusable AnyEvent/socket/runtime fixes rather than CPAN source patches.

The archived CPAN random-tester run is 20260825-135237-11904, target AnyEvent::HTTPD. Its report says Unknown test outcome, but focused reproduction attributes that incomplete result to the defects below.

System-Perl baseline

The exact prerequisite versions were built in an isolated library using system Perl so that AnyEvent's generated constants.pl came from the same interpreter running the tests:

  • AnyEvent 7.17
  • AnyEvent::HTTP 2.25
  • Object::Event 1.23
  • AnyEvent::HTTPD 0.93

With ordinary loopback socket access, the unchanged upstream suite passes:

All tests successful.
Files=13, Tests=64
Result: PASS

The suite completes in approximately two seconds.

JVM backend: delayed/missing EOF

Focused test:

timeout 45 ./jperl t/01_basic_request.t

Observed:

1..4
test_connect timed out at .../AnyEvent/HTTPD/Util.pm line 70.
ok 1 - the path of the request URL was ok
ok 2 - the path of the second request URL was ok
ok 3 - Correct method used
ok 4 - the response text was ok

The response bytes arrive, but the client does not receive EOF. The test only completes after its internal 15-second AnyEvent::Handle timeout returns the accumulated response.

For an HTTP/1.0 request without keep-alive, upstream closes the connection promptly. AnyEvent::HTTPD::HTTPConnection::do_disconnect performs the following sequence:

shutdown$self->{hdl}->{fh}, 1;
$self->{hdl}->on_read(sub {});
$self->{hdl}->on_eof(undef);
my$timer;
$timer = AE::timer 2, 0, sub {
undef$timer;
delete$self->{hdl};
};

Likely investigation areas are socket shutdown, EOF propagation through AnyEvent::Handle, destruction/close of the retained filehandle, and timer-driven handle release. A focused project-owned test should determine which layer owns the defect.

Interpreter backend: callback recursion/stack overflow

Focused test:

timeout 45 ./jperl --interpreter t/01_basic_request.t

Observed:

1..4
# No tests run!
Interpreter error in AnyEvent.pm line 2061: null
StackOverflowError

AnyEvent 7.17 line 2061 is the condition-variable end callback invocation:

subend {
returnif --$_[0]{_ae_counter};
&{ $_[0]{_ae_end_cb} || sub { $_[0]->send } };
}

The JVM stack repeatedly cycles through interpreted callback application and bytecode execution. Reduce this to a small callback/condvar reproducer and fix interpreter callback dispatch or recursion independently of the socket EOF problem.

Context and impact

Core AnyEvent is currently installed under a distropref that skips its broad upstream suite because it includes unsupported fork and optional event-loop surfaces. That policy does not explain this failure: AnyEvent::HTTPD is a downstream, non-forking loopback acceptance gate, and its complete suite passes under system Perl.

The CPAN reports contain many AnyEvent-family modules, including numerous passing downstream distributions. Correct socket teardown and interpreter callback execution therefore have broader value than this one HTTP server.

Acceptance criteria

  • Add a permanent, standard-Perl-validated regression for prompt EOF after the relevant shutdown/handle-release sequence.
  • Make the JVM-focused t/01_basic_request.t complete without the 15-second test_connect timed out warning.
  • Add a small standard-Perl-validated interpreter regression for the condition-variable callback shape around AnyEvent.pm line 2061.
  • Make the interpreter-focused test complete without StackOverflowError.
  • Run the unchanged AnyEvent::HTTPD 0.93 suite successfully on PerlOnJava: 13 files and 64 tests.
  • Verify both backends where the runtime surface is shared.
  • Refresh the CPAN compatibility classification from Unknown test outcome to PASS once the bounded suite completes reliably.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions