4

I've got a python django app where part of it is parsing a large file. This takes forever, so I put a fork in to deal with the processing, allowing the user to continue to browse the site. Within the fork code, there's a bunch of calls to our postgres database, hosted on amazon.

I'm getting the following error:

SSL error: decryption failed or bad record mac

Here's the code:

pid = os.fork()
if pid == 0:
    lengthy_code_here(long)
    database_queries(my_database)
    os._exit(0)

None of my database calls are working, although they were working just fine before I inserted the fork. After looking around a little, it seems like it might be a stale database connection, but I'm not sure how to fix it. Does anyone have any ideas?

1
  • Probably the main thread closed the Db connection, and the forked tries with the same connection object. Use Celery for long-polling requests. Oops, already answered the same. Commented Jun 13, 2012 at 19:10

2 Answers 2

7

Forking while holding a socket open (such as a database connection) is generally not safe, as both processes will end up trying to use the same socket at once.

You will need, at a minimum, to close and reopen the database connection after forking.

Ideally, though, this is probably better suited for a task queueing system like Celery.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! I'm looking at Celery now, but as an alternative -- How would I close and reopen the database connection in python/django?
django.db.connection.close(), I believe.
2

Django in production typically has a process dispatching to a bunch of processes that house django/python. These processes are long running, ie. they do NOT terminate after handling one request. Rather they handle a request, and then another, and then another, etc. What this means is changes that are not restored/cleaned up at the end of servicing a request will affect future requests.

When you fork a process, the child inherits various things from the parent including all open descriptors (file, queue, directories). Even if you do nothing with the descriptors, there is still a problem because when a process dies all it's open descriptors will be cleaned up.

So when you fork from a long running process you are setting yourself up to close all the open descriptors (such as the ssl connection) when the child process dies after it finishes processing. There are ways to prevent this from happening in a fork, but they can sometimes be difficult to get right.

A better design is to not fork, and instead hand off to another process that is either running, or started in a safer manner. For example:

  • at(1) can be used to queue up jobs for later (or immediate) execution
  • message queues can be used to pass messages to other daemons
  • standard IPC constructs such as pipes can be used to communicate to other daemons

update:

If you want to use at(1) you will have to create a standalone script. You can use a serializer to pass the data from django to the script.

2 Comments

Thank you! Can you show me an example of how I might use at(1) to queue it up for immediate execution?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.