-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Update arbiter.py to not leave tmp files around (fix #1327) #1428
Conversation
This patch helped us diagnose the problem, but I don't think it is the best solution. It would be less costly to set the close on exec flag for the temp file after it's inherited by its worker, right after the |
Found those references: http://stackoverflow.com/questions/6125068/what-does-the-fd-cloexec-fcntl-flag-do
|
Oh it looks like there's already a utility for that: close_on_exec |
There's a worker.tmp in the code, is it that temp file we're talking about ? |
I am wrong, |
@benoitc @berkerpeksag I'd like to merge this, but would appreciate one other review. I don't see a better way right now and I've been putting this off for weeks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think your solution is correct, but I don't quite understand why file descriptors of a worker are inheritable by default especially in Python 3.4+.
@@ -565,6 +565,10 @@ def spawn_worker(self): | |||
self.WORKERS[pid] = worker | |||
return pid | |||
|
|||
# Do not inherit the temporary files of other workers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -565,6 +565,10 @@ def spawn_worker(self): | |||
self.WORKERS[pid] = worker | |||
return pid | |||
|
|||
# Do not inherit the temporary files of other workers | |||
for sibling in self.WORKERS.values(): | |||
sibling.tmp.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps a more elegant way would be:
import os
import resource
fd_high = resource.getrlimit(resource.RLIMIT_NOFILE)[0]
os.closerange(3, fd_high)
Or we could store FDs of temp files of workers in a list and pass the highest number as fd_high
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure it would be safe to assume that all open FDs are WorkerTmp
files. We could have any number of log files open at this point, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a point :) So unless we keep tracking file descriptors of those WorkerTmp
files I don't see a better way to solve this problem either.
I'm confused we already set close on exec there : https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/base.py#L106 and we already unlink it there: Normally these files shouldn't be let on the fs then. So the actual question for me is on which system is it reproducible? How do you launch gunicorn ? Anyway why not using |
The workers don't call
We don't close it, though.
As far as I understand, this is not OS-specific and it doesn't matter how you launch Gunicorn.
We need the file to be inheritable. The arbiter unlinks the file, so passing the fd through the fork is the only way the worker can access it. Also, per the documentation [1], "On UNIX, non-inheritable file descriptors are closed in child processes at the execution of a new program, other file descriptors are inherited." The workers do not call [1] https://docs.python.org/3/library/os.html#inheritance-of-file-descriptors |
That's true. We want them inheritable, like i said i'm confused by that ticket :). I don't reproduce the issue there. I'm not sure how you can still have tmp file on disk if they are unlinked. So I guess it's OS specific, or maybe just another systemd crap as it's apparently used there. I would be interrested in knowing more what does systemd or whatever. Anyway the patch is OK, let's merge it. |
They are not in the filesystem, but in the list of open files for the worker processes. You have to call |
Note that I think we can use (Python 3.7 is not released yet :)) |
Still i was not reproducing it when the process is restarted using HUP or USR2 in my systems so something is triggering it.... I guess a better fix would be finally replacing that temporary file trick :) I need to focus on that. @berkerpeksag you mean to have a function cleaning on fork? |
Yes, |
Is this fix merged into a release? When is it expected in an official release? |
Update arbiter.py to not leave tmp files around (fix benoitc#1327)
(deleted) tmp files left around #1327