Giter VIP home page Giter VIP logo

Comments (11)

coolo avatar coolo commented on June 10, 2024

Fixed the URL of the openqa issue - https://github.com/inway/mojo-rabbitmq-client/blob/master/lib/Mojo/RabbitMQ/Client/Channel.pm#L641 is the point of the DESTROY

from mojo-rabbitmq-client.

SPodjasek avatar SPodjasek commented on June 10, 2024

I'm wondering about the right choice of action when a fork is detected.
Should it behave in a similar way to DBIx::Class and create new connection everytime it forks? What about current subscriptions and many other things to take into account...

from mojo-rabbitmq-client.

kraih avatar kraih commented on June 10, 2024

I think it might be smart to just do the same thing Mojo::UserAgent and Mojo::Pg do. Reset the connection pool after fork, and make sure the parent connection does not get corrupted. If nobody else is working on this yet i'll take a look tomorrow.

from mojo-rabbitmq-client.

SPodjasek avatar SPodjasek commented on June 10, 2024

I was just thinking about hypothetical use case when you open client, consume a message, fork and execute some long running task, and then publish a reply on a different channel. This might as well be just some edge case, that will never be thought of.

Resetting connection pool will probably be less error-prone.

from mojo-rabbitmq-client.

coolo avatar coolo commented on June 10, 2024

for the record: I worked around the issue for me by just not having open connections around and using the Publisher API. This is a little slower and it's still possible that we run into this problem, but it reduces the problem for me.

from mojo-rabbitmq-client.

kraih avatar kraih commented on June 10, 2024

Trying to replicate the problem turned out to be way more complicated than i expected. Because a connection created with the Mojo::RabbitMQ::Client promise API results in 24+ circular references that prevent the destruction of the channel. Which also has me a little worried that @coolo's workaround might be leaking memory.

Cycle (1):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B

Unhandled type: GLOB at /usr/lib/perl5/vendor_perl/5.26.2/Devel/Cycle.pm line 107.
Cycle (2):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (3):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                         $M->{'error'} => \@N
                               $N->[0] => \&O
                  $O variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (4):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                         $M->{'error'} => \@N
                               $N->[0] => \&O
                  $O variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'result'} => \@R
                               $R->[0] => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (5):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                          $M->{'open'} => \@S
                               $S->[0] => \&T
                  $T variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (6):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                          $M->{'open'} => \@S
                               $S->[0] => \&T
                  $T variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'result'} => \@R
                               $R->[0] => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (7):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
        $Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
                               $V->[0] => \&W
                       $W variable $cb => \$X
                                   $$X => \&Y
                     $Y variable $self => \$Z
                                   $$Z => \%Mojo::RabbitMQ::Client::Method::A

Cycle (8):
        $Mojo::RabbitMQ::Client::Method::A->{'channel'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
        $Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
                               $V->[0] => \&W
               $W variable $failure_cb => \$AA
                                  $$AA => \&AB
                    $AB variable $self => \$Z
                                   $$Z => \%Mojo::RabbitMQ::Client::Method::A

Cycle (9):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C

Cycle (10):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                         $M->{'error'} => \@N
                               $N->[0] => \&O
                  $O variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (11):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                         $M->{'error'} => \@N
                               $N->[0] => \&O
                  $O variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'result'} => \@R
                               $R->[0] => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (12):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                          $M->{'open'} => \@S
                               $S->[0] => \&T
                  $T variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (13):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                          $M->{'open'} => \@S
                               $S->[0] => \&T
                  $T variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'result'} => \@R
                               $R->[0] => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (14):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
        $Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
                               $V->[0] => \&W
                       $W variable $cb => \$X
                                   $$X => \&Y
                     $Y variable $self => \$Z
                                   $$Z => \%Mojo::RabbitMQ::Client::Method::A

Cycle (15):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
        $Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
                               $V->[0] => \&W
               $W variable $failure_cb => \$AA
                                  $$AA => \&AB
                    $AB variable $self => \$Z
                                   $$Z => \%Mojo::RabbitMQ::Client::Method::A

Cycle (16):
        $Mojo::RabbitMQ::Client::Method::A->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (17):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'channels'} => \%D
                             $D->{'1'} => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (18):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'client'} => \%Mojo::RabbitMQ::Client::C
        $Mojo::RabbitMQ::Client::C->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (19):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                         $M->{'error'} => \@N
                               $N->[0] => \&O
                  $O variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (20):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                         $M->{'error'} => \@N
                               $N->[0] => \&O
                  $O variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'result'} => \@R
                               $R->[0] => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (21):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                          $M->{'open'} => \@S
                               $S->[0] => \&T
                  $T variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'ioloop'} => \%Mojo::IOLoop::E
         $Mojo::IOLoop::E->{'reactor'} => \%Mojo::Reactor::Poll::F
        $Mojo::Reactor::Poll::F->{'timers'} => \%G
        $G->{'d2032e3a07bd0d1693d59c00d16d9d53'} => \%H
                            $H->{'cb'} => \&I
                       $I variable $cb => \$J
                                   $$J => \&K
                 $K variable $consumer => \$L
                                   $$L => \%Mojo::RabbitMQ::Client::Method::A

Cycle (22):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'events'} => \%M
                          $M->{'open'} => \@S
                               $S->[0] => \&T
                  $T variable $promise => \$P
                                   $$P => \%Mojo::Promise::Q
         $Mojo::Promise::Q->{'result'} => \@R
                               $R->[0] => \%Mojo::RabbitMQ::Client::Channel::B

Cycle (23):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
        $Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
                               $V->[0] => \&W
                       $W variable $cb => \$X
                                   $$X => \&Y
                     $Y variable $self => \$Z
                                   $$Z => \%Mojo::RabbitMQ::Client::Method::A

Cycle (24):
        $Mojo::RabbitMQ::Client::Method::A->{'events'} => \%AC
                      $AC->{'success'} => \@AD
                              $AD->[0] => \&AE
                    $AE variable $self => \$AF
                                  $$AF => \%Mojo::RabbitMQ::Client::Channel::B
        $Mojo::RabbitMQ::Client::Channel::B->{'queue'} => \%Mojo::RabbitMQ::Client::LocalQueue::U
        $Mojo::RabbitMQ::Client::LocalQueue::U->{'drain_code_queue'} => \@V
                               $V->[0] => \&W
               $W variable $failure_cb => \$AA
                                  $$AA => \&AB
                    $AB variable $self => \$Z
                                   $$Z => \%Mojo::RabbitMQ::Client::Method::A

from mojo-rabbitmq-client.

kraih avatar kraih commented on June 10, 2024

Pretty much everything leaks a lot as it turns out, including the publisher API (8 circular references). I'll be sending a patch for that.

from mojo-rabbitmq-client.

AdamWill avatar AdamWill commented on June 10, 2024

So, I'm now trying to use the openQA AMQP bits to publish to fedora-messaging (what fun we're all having!) One thing I noticed is these errors popping up in the logs:

Aug 01 23:40:59 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_handle" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 372.
Aug 01 23:40:59 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_handle" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 372.
Aug 01 23:41:04 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_read" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 374.
Aug 01 23:41:04 openqa-stg01.qa.fedoraproject.org openqa[12692]: Mojo::Reactor::Poll: I/O watcher failed: Can't call method "_read" on an undefined value at /usr/share/perl5/vendor_perl/Mojo/RabbitMQ/Client.pm line 374.

those are happening here:

  # Connection established
  $stream->on(timeout => sub { $self->_error($id, 'Inactivity timeout') });
  $stream->on(close => sub { $self->_handle($id, 1) });
  $stream->on(error => sub { $self && $self->_error($id, pop) });
  $stream->on(read => sub { $self->_read($id, pop) });
  $cb->();

it seems $id is undefined sometimes. I honestly am not sure exactly how or by what it's supposed to be defined at the point those subroutines are called, all this async stuff screws with my head. But is it related to this, perhaps? If not, I can file a separate issue. @kraih @coolo have you seen these errors also?

from mojo-rabbitmq-client.

okurz avatar okurz commented on June 10, 2024

yes, we see these errors all the time reproducibly e.g. on openqa.opensuse.org. The originally referenced progress ticket also links to another ticket that is describing this issue as well: https://progress.opensuse.org/issues/52961
so for sure there seems to be no relevant functional impact but no clean shutdown of the streams triggering the above error.

from mojo-rabbitmq-client.

okurz avatar okurz commented on June 10, 2024

@AdamWill at least the warnings about undef objects are handled in #36 . Not sure if this is the last missing piece to close this issue though.

from mojo-rabbitmq-client.

AdamWill avatar AdamWill commented on June 10, 2024

Thanks 👍

from mojo-rabbitmq-client.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.