Sorry for my above answer I think the actual locks should go like this, so 
all threads can actually go to the wait line while _populating is True.

def _populate(self):

    self.lock.acquire()
    
    if self._populating:
        self.lock.wait()
        self.lock.release()
        return
        
    self._populating = True
    
    self.lock.release()
    
    ...

    self.lock.acquire()
    self._populating = False
    self.lock.notify_all()
    self.lock.release()



El lunes, 11 de julio de 2016, 22:14:04 (UTC-3), Cristiano Coelho escribió:
>
> Wouldn't a standard Lock do the trick? Also you are still vulnerable to a 
> race condition when reading self._populating, if the goal is to avoid 
> populating the object more than once in a short interval (in a case where 
> multiple requests hit the server before the object is initialized for the 
> first time?) you are still running all the critical code on all threads if 
> they check self.populating before it is set to True.
>
> Would a condition work better in this case? Something like this.. (add any 
> missing try/finally/with that might be required), warning, NOT TESTED, just 
> an idea.
> The below code will not be prone to race conditions as the variables are 
> always read/set under a lock, and also the critical section code will be 
> only executed ONCE even if multiple threads attempt to run it at once, 
> while still locking all threads to prevent returning before the code is 
> done.
>
> def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None
> , namespace=None):
>         
>         ...
>
>     self._populating = False
>     self.lock = threading.Condition()
>
> def _populate(self):
>
>     self.lock.acquire()
>     
>     if self._populating:
>         self.lock.wait()
>         self.lock.release()
>         return
>         
>     self._populating = True
>
>     ...
>
>     self._populating = False
>     self.lock.notify_all()
>     self.lock.release()
>
>
>
>
>
> El lunes, 11 de julio de 2016, 10:08:50 (UTC-3), a.br...@rataran.com 
> escribió:
>>
>> Hello everyone.
>>
>> As suggested by Markus on django-users group, I'm posting this here too.
>>
>> -------
>>
>> I'm using django (1, 10, 0, u'beta', 1).
>>
>> When I try to reverse url in shell everything goes fine.
>>
>> When under nginx/uwsgi with many concurrent request I get 
>>
>> ... /local/lib/python2.7/site-packages/django/urls/resolvers.py", line 
>> 241, in reverse_dict
>>     return self._reverse_dict[language_code]
>> KeyError: 'it'
>>
>> After a wile I figured out that RegexURLResolver is memoized by 
>> get_resolver and so it acts like a singleton for a certain number of 
>> requests.
>>
>> Analyzing the code of  RegexURLResolver I found that the method 
>> _poupulate will return directly if it has been called before and not yet 
>> finished.
>>
>>     ...
>>     def _populate(self):
>>         if self._populating:
>>             return
>>         self._populating = True
>>     ...  
>>
>> if used for recursive call in a single thread this will not hurt, but in 
>> my case in uwsgi multi thread mode I got the error.
>>
>> here is my quick and dirty fix:
>>
>> class RegexURLResolver(LocaleRegexProvider):
>>     def __init__(self, regex, urlconf_name, default_kwargs=None, 
>> app_name=None, namespace=None):
>>         
>>         ...
>>
>>         self._populating = False
>>         self.RLock = threading.RLock()
>>
>>         ...
>>
>>    def _populate(self):
>>         if self._populating:
>>             self.RLock.acquire()
>>             self.RLock.release()
>>             return
>>         self._populating = True
>>         self.RLock.acquire()
>>         
>>         ...
>>
>>         self._populating = False
>>         self.RLock.release()
>>
>>
>> Does anyone know if there is a better solution?
>>
>> Thank you.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/922ca727-dd60-41dd-9b78-b8d8fe9ebd16%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to