mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Make the session thread safe.
As sessions in pgAdmin4 are filesystem based session, they need locking for avoiding the access from multiple threads, specially running as an WSGI application. Fixes #3547
This commit is contained in:
parent
70c95fcdd5
commit
013ad7446f
@ -20,5 +20,6 @@ Bug fixes
|
|||||||
| `Bug #3407 <https://redmine.postgresql.org/issues/3407>`_ - Fix keyboard shortcuts layout in the preferences panel.
|
| `Bug #3407 <https://redmine.postgresql.org/issues/3407>`_ - Fix keyboard shortcuts layout in the preferences panel.
|
||||||
| `Bug #3461 <https://redmine.postgresql.org/issues/3461>`_ - Ensure that refreshing a node also updates the Property list.
|
| `Bug #3461 <https://redmine.postgresql.org/issues/3461>`_ - Ensure that refreshing a node also updates the Property list.
|
||||||
| `Bug #3528 <https://redmine.postgresql.org/issues/3528>`_ - Handle connection errors properly in the query tool.
|
| `Bug #3528 <https://redmine.postgresql.org/issues/3528>`_ - Handle connection errors properly in the query tool.
|
||||||
|
| `Bug #3547 <https://redmine.postgresql.org/issues/3578>`_ - Make session implementation thread safe
|
||||||
| `Bug #3558 <https://redmine.postgresql.org/issues/3558>`_ - Fix sort/filter dialog editing issue.
|
| `Bug #3558 <https://redmine.postgresql.org/issues/3558>`_ - Fix sort/filter dialog editing issue.
|
||||||
| `Bug #3578 <https://redmine.postgresql.org/issues/3578>`_ - Ensure sql for Role should be visible in SQL panel for GPDB.
|
| `Bug #3578 <https://redmine.postgresql.org/issues/3578>`_ - Ensure sql for Role should be visible in SQL panel for GPDB.
|
||||||
|
@ -24,6 +24,7 @@ import random
|
|||||||
import string
|
import string
|
||||||
import time
|
import time
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
from threading import Lock
|
||||||
from flask import current_app, request, flash, redirect
|
from flask import current_app, request, flash, redirect
|
||||||
from flask_login import login_url
|
from flask_login import login_url
|
||||||
from pgadmin.utils.ajax import make_json_response
|
from pgadmin.utils.ajax import make_json_response
|
||||||
@ -50,6 +51,9 @@ def _calc_hmac(body, secret):
|
|||||||
).decode()
|
).decode()
|
||||||
|
|
||||||
|
|
||||||
|
sess_lock = Lock()
|
||||||
|
|
||||||
|
|
||||||
class ManagedSession(CallbackDict, SessionMixin):
|
class ManagedSession(CallbackDict, SessionMixin):
|
||||||
def __init__(self, initial=None, sid=None, new=False, randval=None,
|
def __init__(self, initial=None, sid=None, new=False, randval=None,
|
||||||
hmac_digest=None):
|
hmac_digest=None):
|
||||||
@ -111,8 +115,9 @@ class CachingSessionManager(SessionManager):
|
|||||||
def _normalize(self):
|
def _normalize(self):
|
||||||
if len(self._cache) > self.num_to_store:
|
if len(self._cache) > self.num_to_store:
|
||||||
# Flush 20% of the cache
|
# Flush 20% of the cache
|
||||||
while len(self._cache) > (self.num_to_store * 0.8):
|
with sess_lock:
|
||||||
self._cache.popitem(False)
|
while len(self._cache) > (self.num_to_store * 0.8):
|
||||||
|
self._cache.popitem(False)
|
||||||
|
|
||||||
def new_session(self):
|
def new_session(self):
|
||||||
session = self.parent.new_session()
|
session = self.parent.new_session()
|
||||||
@ -122,59 +127,64 @@ class CachingSessionManager(SessionManager):
|
|||||||
if request.path.startswith(sp):
|
if request.path.startswith(sp):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
self._cache[session.sid] = session
|
with sess_lock:
|
||||||
|
self._cache[session.sid] = session
|
||||||
self._normalize()
|
self._normalize()
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def remove(self, sid):
|
def remove(self, sid):
|
||||||
self.parent.remove(sid)
|
with sess_lock:
|
||||||
if sid in self._cache:
|
self.parent.remove(sid)
|
||||||
del self._cache[sid]
|
if sid in self._cache:
|
||||||
|
del self._cache[sid]
|
||||||
|
|
||||||
def exists(self, sid):
|
def exists(self, sid):
|
||||||
if sid in self._cache:
|
with sess_lock:
|
||||||
return True
|
if sid in self._cache:
|
||||||
return self.parent.exists(sid)
|
return True
|
||||||
|
return self.parent.exists(sid)
|
||||||
|
|
||||||
def get(self, sid, digest):
|
def get(self, sid, digest):
|
||||||
session = None
|
session = None
|
||||||
if sid in self._cache:
|
with sess_lock:
|
||||||
session = self._cache[sid]
|
if sid in self._cache:
|
||||||
if session.hmac_digest != digest:
|
session = self._cache[sid]
|
||||||
session = None
|
if session.hmac_digest != digest:
|
||||||
|
session = None
|
||||||
|
|
||||||
# reset order in Dict
|
# reset order in Dict
|
||||||
del self._cache[sid]
|
del self._cache[sid]
|
||||||
|
|
||||||
if not session:
|
if not session:
|
||||||
session = self.parent.get(sid, digest)
|
session = self.parent.get(sid, digest)
|
||||||
|
|
||||||
# Do not store the session if skip paths
|
# Do not store the session if skip paths
|
||||||
for sp in self.skip_paths:
|
for sp in self.skip_paths:
|
||||||
if request.path.startswith(sp):
|
if request.path.startswith(sp):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
self._cache[sid] = session
|
self._cache[sid] = session
|
||||||
self._normalize()
|
self._normalize()
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def put(self, session):
|
def put(self, session):
|
||||||
self.parent.put(session)
|
with sess_lock:
|
||||||
|
self.parent.put(session)
|
||||||
|
|
||||||
# Do not store the session if skip paths
|
# Do not store the session if skip paths
|
||||||
for sp in self.skip_paths:
|
for sp in self.skip_paths:
|
||||||
if request.path.startswith(sp):
|
if request.path.startswith(sp):
|
||||||
return
|
return
|
||||||
|
|
||||||
if session.sid in self._cache:
|
if session.sid in self._cache:
|
||||||
try:
|
try:
|
||||||
del self._cache[session.sid]
|
del self._cache[session.sid]
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self._cache[session.sid] = session
|
self._cache[session.sid] = session
|
||||||
self._normalize()
|
self._normalize()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user