-
Notifications
You must be signed in to change notification settings - Fork 695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
timer decorator and cheaped workers #58
Comments
After a while logs are filled with
This is probably since we are sending signals all the time (probably master does that), but there is no worker to handle them. |
The quick solution would be using a mule for that. The other one would be waking up a worker when a signal has to be routed. But it is that kind of behaviour that users have to choose, so having an "invasive" default is not a good idea. Another approach would be accounting handled signals in addition to requests, so the cheap/cheaper/idle modes would be more smart about that. |
There is another issue I've spotted, signals and cheaper don't mix to well:
I think that with dynamic worker process management there will always be issues like this, so IMHO it should be better to just spawn mule for signal handling when we have none spawned and user registers new timer. Moving signal handling to dedicated process will free us from the need to handle growing number of corner cases while uWSGI will be picking new tricks for worker process management. |
I left my vassal running and after few hours I get constant segfaults:
|
do you have --enable-threads ? that kind of error happens when the gil is not get before calling python functions |
No I don't:
|
i do not see spawned mules, are not you are testing them ? |
No, this is my development vm, I have there one app I'm working on, I've added uWSGI timer to my django settings so that uWSGI will restart after code is modified. After adding --processes 8 and --cheaper 1 I've spotted this issue. |
OT use py-auto-reload = n (n is in seconds) to accomplish that |
I am starting to think not registering signal handlers in the master should not be allowed while in cheap/cheaper modes |
I've got another segfult, looking at logs I see this pattern:
After that it's always the first worker that gets segfault. |
So, the new master is almost ready. Time to make a decision. How to deal with worker signal handlers when in cheap mode (or the corresponding worker is cheaped) ? Just spawn the worker ? drop the signal ? Other solutions ? |
I would spawn new worker, if user want to handle such signal that that should take precedence over cheaper mode |
What about this one? |
Is this issue still being addressed or investigated? My current solution is to:
But it would be nicer if the uWSGI master process would spawn a new worker when a timer event fires. |
We have 3 events to manage:
The only true problem is deciding if this is the default behaviour or not |
Not sure if you are asking for my opinion/observation or just stating you're current thought.: If an option helps, then: The "spawn at least a worker when 'worker' target is used." option seems the most correct/expected. If I set a timer in my code I would expect (when the timer event fires) that if no workers were present then one would be created to service the timer event. Otherwise, if you're still thinking about this issue at an software architectural level, then I understand. Thanks |
Another idea on this topic: The @Timer() decorator supports the "target='spooler'" argument, if the @Timer() decorator also supported the "spooler='/path/to/spooler'" argument (which I don't think it does) then I could dedicate a spooler process to handling timer only requests. Not sure if this is easier than having timer events spawning new workers. The other reason this method would be useful to me is that I could force all of the logging from the dedicated "timer" spooler to a separate file. |
This is something to do absolutely (that part was never aligned with the multiple spooler codebase introduced in 1.4). In the mean time you could use a mule (the target syntax take the mule0, mule1 syntax to send requests to a specific mule) |
To me, it seems logical (= I have expected) that signals are delivered only when worker is active, thus - no process - no delivery attempt. |
There are really dozens of scenarios here, this is why we are still searching for a solution. Some note:
The current solution on top of the list is having a fallback target (something like --signal-fallback mule) This is easy to implement (and probably this is the reason why it is on top of the list ;) Other solutions require heavy-lifting of the core (like adding a policy field to the signal table that describe how an unroutable signal should behave). Something to think for 2.1 |
What about simple option which (when set) will limit sending signals only to active workers - does it also requires heavy-lifting? |
If you use "worker" as target the signal will be routed to the first available (alive) worker so it should be more than enough for you. The problem (if i understand correctly) is when you have all workers dead. |
No, the problem arises when some workers are dead (like described in #775 - one is active, 4 are not), and when I need some periodical wake-ups in all active workers. |
So is the "workers" (with the final 's') target, right ? You need to trigger the signal to all of the workers but it fails as some of them are dead ? |
Exactly the problem - target is "workers", alive are signalled but dead are not and signals are accumulated in the queue, eventually overflowing it. |
Yes, it could be an interesting approach (i mean the "active-workers" target). I will back to you soon |
Additional note - not sure if it belongs here, but definitely related - allowing specifying target in signal sources (signal/timer/cron/etc) would add a lot of flexibility. |
I have pushed (in both 2.0 and 2.1) the 'active-workers' target. Let me know |
Seems to work with signal delivery, but produces segfault when attempting to kill('HUP', $$) from signal handler (this did work properly in 2.0.8). To avoid clutter here all details are in gist: https://gist.github.com/aldem/a19eef9cd58690534a5c |
This is exactly the kind of problems i was referring in the mailing list thread. The segfault is caused by the new atexit hook in the perl plugin :) I'll try to understand if we can have a workaround |
Ok, now it should work reliably. The atexit procedure for perl checks if there is already a running function (basically it checks for a running request or a running signal handler), and if so it skips normal interpreter destruction. |
Yes, it works - thanks! Though I don't see how atexit() was involved here - it wasn't used at all in my test case... |
The new plugin version correctly (tries) to call perl_destruct and perl_free. Those functions if called in a signal handler while another subroutine is running, tend to explodes. |
What about marking worker as "needs cleanup" if it was busy (in signal/request handler) and cleaning up again (perl_dectruct/perl_free) once all processing is completed? |
I'm confused on the progress here; I'm looking for workers to be automatically spawned when a timer event/decorator fires and no workers are active (using the "idle") parameter in the config. Based discussion in this thread for the past few days, it sounds like automatically spawning workers to handle timer events "is bad". |
@jsivak it depends on the context. if your app is fully preforked, spawning it on-demand will be a matter of few milliseconds. we are trying to cover different use cases |
That type of delay is fine for my needs; I'm running my web app's with "lazy-apps=true" set; not exactly sure if that's what you mean when you say "fully preforked". If the "auto spawning" is in the uwsgi-2.0 branch on github, then let me know how I can test it (what config file settings to set) and I'll give it a try. |
Just got bit with this issue on one of my older apps (running uwsgi 2.0.8).. Did any resolution for this issue get decided on or implemented in a newer version? Thanks |
If I use timer decorator and all my workers will be cheaped than also timer will stop working since it is executed in first worker. Docs say that timer can be executed using spooler instead of worker, but it doesn't say anything about cheaping workers with --idle option.
This should be either:
timerapp.ini:
timerapp.py:
app log:
The text was updated successfully, but these errors were encountered: