简体   繁体   中英

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.

When the python program finishes, the connection is still established in charge of a child.

So a child inherits its parent resource when parent dies.

doing a 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.

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.

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. 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 :

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. 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. 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. 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.

#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. 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:

from subprocess import Popen

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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