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
Fixed #24064 - Prevented database access in compile time in spatialite models #3821
Conversation
It looks like the receiver is ran multiple times (on every connection creation). What about disconnecting it upon first call. I guess this might not be thread safe however. |
@charettes, well, I think the fact it is running every time is not good too, PR is more to discuss the idea. |
I don't have Spatialite installed locally but what about those changes From 9be0ec918ebf703cd0fc93bfa6a172e3f69ac97c Mon Sep 17 00:00:00 2001
From: Simon Charette <charette.s@gmail.com>
Date: Wed, 31 Dec 2014 17:26:26 -0500
Subject: [PATCH] Add spatial version related fields once.
---
django/contrib/gis/db/backends/spatialite/models.py | 21 +++++++++++----------
django/dispatch/dispatcher.py | 4 ++++
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/django/contrib/gis/db/backends/spatialite/models.py b/django/contrib/gis/db/backends/spatialite/models.py
index fc8cd11..95ee1e0 100644
--- a/django/contrib/gis/db/backends/spatialite/models.py
+++ b/django/contrib/gis/db/backends/spatialite/models.py
@@ -74,14 +74,15 @@ def add_spatial_version_related_fields(sender, **kwargs):
Ticket #24064 - Need to establish connection first and then add fields
to prevent database operations on compile time.
"""
- srtext_field_added = 'srtext' in SpatialiteSpatialRefSys._meta.get_all_field_names()
- type_field_added = 'type' in SpatialiteGeometryColumns._meta.get_all_field_names()
- if srtext_field_added and type_field_added:
- return
- spatial_version = connection.ops.spatial_version[0]
- if spatial_version >= 4:
- SpatialiteSpatialRefSys.add_to_class('srtext', models.CharField(max_length=2048))
- SpatialiteGeometryColumns.add_to_class('type', models.IntegerField(db_column='geometry_type'))
- else:
- SpatialiteGeometryColumns.add_to_class('type', models.CharField(max_length=30))
+ if connection_created.disconnect(add_spatial_version_related_fields, sender=DatabaseWrapper):
+ srtext_field_added = 'srtext' in SpatialiteSpatialRefSys._meta.get_all_field_names()
+ type_field_added = 'type' in SpatialiteGeometryColumns._meta.get_all_field_names()
+ if srtext_field_added and type_field_added:
+ return
+ spatial_version = connection.ops.spatial_version[0]
+ if spatial_version >= 4:
+ SpatialiteSpatialRefSys.add_to_class('srtext', models.CharField(max_length=2048))
+ SpatialiteGeometryColumns.add_to_class('type', models.IntegerField(db_column='geometry_type'))
+ else:
+ SpatialiteGeometryColumns.add_to_class('type', models.CharField(max_length=30))
connection_created.connect(add_spatial_version_related_fields, sender=DatabaseWrapper)
diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py
index 907f7fb..3a7b678 100644
--- a/django/dispatch/dispatcher.py
+++ b/django/dispatch/dispatcher.py
@@ -165,9 +165,13 @@ class Signal(object):
for index in range(len(self.receivers)):
(r_key, _) = self.receivers[index]
if r_key == lookup_key:
+ disconnected = True
del self.receivers[index]
break
+ else:
+ disconnected = False
self.sender_receivers_cache.clear()
+ return disconnected
def has_listeners(self, sender=None):
return bool(self._live_receivers(sender))
--
1.9.1 |
@charettes, well, it works, but I don't understand the reason to check |
buildbot, test this please. |
@coldmind, it's to prevent two concurrent threads from creating a race condition where the signal is dispatched twice. |
buildbot, test on trusty. |
@charettes, @timgraham, due to tests, disconnection is called once, so seems no need to have check if field already added to model (see diff above). But I'm afraid there can be situation where it could be. What do you think? |
Simon, is this a different problem from what dispatch_uid attempts to solve? |
Yes, This is trying to prevent a race condition in a multi-threaded environment (not reproducible during tests) such as |
buildbot, test on trusty. |
I re-retriggered the build since the failures seems unrelated. |
Could you move the |
@timgraham, sure, going to add some tests for dispatcher. |
buildbot, test this please. |
Note that disconnect is documented https://docs.djangoproject.com/en/dev/topics/signals/#disconnecting-signals, an update is needed there too. |
del self.receivers[index] | ||
break | ||
else: | ||
disconnected = False |
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 could move this line above the for loop and get rid of the else that way.
buildbot, test this please. |
jenkins failed again with |
No worries, this is likely fine. Will commit shortly. |
Here is the patch that can fix problem.
Ideas about improvements are welcome.