简体   繁体   English

子级继承的Python RabbitMQ连接

[英]Python RabbitMQ connection inherited by child

The problem is the following. 问题如下。 Call a python program which does two thing : connect to a rabbitmq server and calls ac program that spawn two process. 调用执行以下两项操作的python程序:连接到Rabbitmq服务器,并调用产生两个进程的ac程序。

When the python program finishes, the connection is still established in charge of a child. 当python程序完成时,仍将建立连接以负责子进程。

So a child inherits its parent resource when parent dies. 因此,当父母去世时,孩子会继承其父母资源。

doing a netstat -putan | grep rabbitmqip 做一个netstat -putan | grep rabbitmqip netstat -putan | grep rabbitmqip

tcp  0 0 localhost:39744   rabbitmqip:5672 ESTABLISHED 25693/child

This is what i get when python script finished. 这是我在python脚本完成时得到的。

I would imagine that the connection would be lost in a case like this. 我可以想象在这种情况下连接会丢失。

This seems to happen with connections to a RabbitMQ server, we cant reproduce with regular TCP connections. 这似乎发生在与RabbitMQ服务器的连接上,我们无法通过常规的TCP连接进行复制。

Has anyone had this issue before ? 以前有人遇到过这个问题吗? is there any workaround ? 有什么解决方法吗?

The python code would be my rabbit consumer and the c program would be scripts in background that are spawned or killed based on the worker's job. python代码将是我的兔子用户,而c程序将是后台的脚本,这些脚本会根据工人的工作而产生或杀死。 I cant have the connection established when i kill the consumer, regardless spawns being active or not because then the children would get messages which they dont understand from the queue. 当我杀死使用者时,无论刷新是否活跃,我都无法建立连接,因为那样子节点将从队列中获得他们不理解的消息。

Code as example : 代码示例:

Python : Python:

connection = pika.BlockingConnection(pika.ConnectionParameters(host='RabbitServer'))
print ("Starting Child...")
system("/home/path/test/child")
print ("Done")

Child program. 子程序。

pid_t pstartId, sessionId;

// Fork 1
pstartId = fork();
if (pstartId < 0) {
    printf("The System can not create a proccess. \n");
    perror("fork");
    exit(EXIT_FAILURE);
}

if (pstartId > 0) { exit(EXIT_SUCCESS);}

// Fork 2
pstartId = fork();
if (pstartId < 0) {
    printf("The System can not create a proccess. \n");
    perror("fork");
    exit(EXIT_FAILURE);
}

if (pstartId > 0) {exit(EXIT_SUCCESS);}

if ((sessionId = setsid()) < 0) {
    printf("The System can not set a id session. \n");
    perror("setid");
    exit(EXIT_FAILURE);
}

if (chdir("/") < 0) {
    printf("The System can not change dir /. \n");
    perror("chdir");
    exit(EXIT_FAILURE);
}

while(1){
    syslog(LOG_INFO, "I'm a child");
    sleep(1);
}

When you spawn a subprocess via fork() in unix the child process inherits all of the parent's open file descriptors. 当您通过unix中的fork()生成子进程时,子进程将继承父级的所有打开文件描述符。 The child process is responsible for closing the descriptors it doesn't need. 子进程负责关闭不需要的描述符。

Your code is calling fork twice, once indirectly via os.system() and then again directly in your C code. 您的代码两次调用fork,一次通过os.system()间接调用,然后再次直接在C代码中调用。 So you have two ways of dealing with this: 因此,您有两种处理方式:

The first is to close all of the unused file descriptors you don't need in the child process of your C code. 第一种是关闭在C代码的子进程中不需要的所有未使用的文件描述符。 This is generally a good practice, if you don't it isn't uncommon to run out of file descriptors in your system if you spawn many children and they all get copies of their parent's fds. 通常,这是一个好习惯,如果您不这样做,那么如果您生了许多孩子并且他们都获得了其父母fds的副本,那么在系统中用尽文件描述符的情况并不罕见。

#include <unistd.h>
#def MAXFD 256

void close_fds() {
  int i;
  for (i = 3; i < MAXFD; i++) {
    close(i);
  }
}

The other option would be to have the file descriptors closed in the fork call made by Python. 另一个选择是在Python进行的fork调用中关闭文件描述符。 You aren't able to do that if you call os.system() , but you have this option if you make the nearly equivalent call with the subprocess module: 你是不是能够做到这一点,如果你调用os.system()但是如果你做与几乎等同的调用你有这个选项subprocess模块:

from subprocess import Popen

Popen("/home/path/test/child", close_fds=True).wait()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM