[ 
https://issues.apache.org/jira/browse/QPID-5637?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Brian Bouterse updated QPID-5637:
---------------------------------

    Attachment: pid_aware_selector.patch

> qpid.messaging Issues With Forking
> ----------------------------------
>
>                 Key: QPID-5637
>                 URL: https://issues.apache.org/jira/browse/QPID-5637
>             Project: Qpid
>          Issue Type: Bug
>          Components: Python Client
>    Affects Versions: 0.24
>            Reporter: Brian Bouterse
>            Priority: Blocker
>             Fix For: 0.18, 0.22, 0.24, 0.26, 0.27
>
>         Attachments: celery_worker_output.txt, pid_aware_selector.patch, 
> tasks.py
>
>
> qpid.messaging has an issue with forking in the following situation.
> 1.  A parent Python process imports and uses qpid.messaging to connect to a a 
> Qpid broker
> 2.  The parent process forks a child process
> 3.  The child process imports qpid.messaging and tries to connect to a Qpid 
> broker.
> I expected to see the child process use qpid.messaging normally as it would 
> if it weren't forked in the way described above.  Instead, the server 
> receives the opening of a TCP socket, but the client never sends the AMQP 
> protocol announcement.
> [Forking bring child descriptors with 
> it|http://man7.org/linux/man-pages/man2/fork.2.html].  I expected the file 
> descriptors on the parent and the child to be the same, and to reference the 
> same socket, so I expect qpid.messaging to work without any modification.  
> Surprisingly, it does not.
> There is at least one place where I do understand how this can be avoided.  
> One of the issues is that the file descriptors registered by the Selector 
> object inside of qpid.messaging are stale after the fork.  The Selector 
> object uses a singleton pattern to provide a reference to the same Selector 
> object no matter how many times you call it.  This selector object already 
> has registered file descriptors with the filesystem, which allow the selector 
> to read/write data in an I/O efficient manner.  See the attached 
> [pid_aware_selector.patch] for an example of this.
> The [pid_aware_selector.patch] does allow communication to flow, but  queue 
> creation and deletion sometimes fail in strange ways.  For instance, in the 
> child process, code that creates a queue, reads information about that queue 
> next.  The queue was created, yet the read says that the queue can't be 
> found.  Very strange.  You can see those things fail using the following 
> example:
> 1.  clone our fork of kombu:       `git clone g...@github.com:pulp/kombu.git`
> 2.  Change into the kombu folder     `cd kombu`
> 3.  Switch to the branch containing the qpid code:  `git checkout 
> pulp-dep-3.0.15-with-qpid`
> 4.  Install kombu onto your system or virtualenv (I do it systemwide using 
> sudo):   `sudo python setup.py develop`
> 5.  install celery version 3.1.11.  I do it using pip.    `sudo pip install 
> celery==3.1.11`
> 6.  Install qpid.messaging and qpidtoollibs.  One way I do it is systemwide 
> using pip.      `sudo pip install qpid-tools qpid-python`
> 7.  Start up qpidd (We've been testing with 0.24 and auth off).      `sudo -u 
> qpidd qpidd --auth=no`
> 8.  Put the attached file tasks.py into a directory
> 9.  Open two terminals and change their working directory to be the same as 
> step 8.
> 10.  In one one terminal start the celery worker        `celery worker -A 
> tasks --loglevel=INFO -c1`
> 11.  In the other terminal dispatch 10 tasks             `python tasks.py`
> You should see exceptions raised similar to those in the attached file 
> [celery_worker_output.txt]
> Note, that the code on the pulp-dep-3.0.15-with-qpid branch of kombu monkey 
> patches qpid.messaging with the selector patch referenced above, and also one 
> or two other bugfix patches.  You can see that [monkey patching done 
> here|https://github.com/pulp/kombu/blob/pulp-dep-3.0.15-with-qpid/kombu/transport/qpid.py#L45].
>   This should have no implications on this issue, but I want to be explicit 
> about it.
> A potential fix:  Celery supports a callback after child processes are 
> forked, allowing the call to cleanup/reset exactly these types of things.  I 
> could wire up that callback if such a thing existed on qpid.messaging.  For 
> testing purposes, you could put a call to this cleanup method in the 
> 'sometask' code before the call to controller.inspect().active_queues().  
> This would be similar in timing to a post fork cleanup/reset call.
> Note: the original connection and associated senders/receivers/sessions are 
> still in use by the parent process, so calling close() is not the right thing 
> to do either.  It's like the connection needs to be forgotten, and the file 
> descriptors unregistered from the child process.



--
This message was sent by Atlassian JIRA
(v6.2#6252)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@qpid.apache.org
For additional commands, e-mail: dev-h...@qpid.apache.org

Reply via email to