You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have multiple threads accessing the same server object. Each thread creates a new connection to the same server. In the search operation, the schema from the server is accessed by the connection.
For the write operation, a lock is used. However, the read operation is not protected. If another thread now reads the schema it is None and the attributes from the search operation can not be decoded properly. The attributes dictionary is equal to the raw_attributes dictionary. For example, uuids are returned in bytes instead of a string.
Here is an example to reproduce the behavior:
server = ldap3.Server("ldaps://test.ldap", connect_timeout=5, get_info=ldap3.SCHEMA)
conn_opts = {'auto_bind': None,
'client_strategy': ldap3.SAFE_SYNC,
'authentication': ldap3.SIMPLE,
'user': '****',
'password': '****'}
def search():
connection = ldap3.Connection(server, **conn_opts)
connection.bind()
_, _, response, _ = connection.search(search_base="dc=test,dc=ldap",
search_scope=ldap3.SUBTREE,
search_filter="(&(sAMAccountName=*)(objectClass=person)(sAMAccountName=foo))",
attributes=["objectGUID"])
result = response[0].get('attributes')
if isinstance(result["objectGUID"], list) and isinstance(result["objectGUID"][0], bytes):
print(f"UUID is a byte array!")
connection.unbind()
thread_pool = concurrent.futures.ThreadPoolExecutor(max_workers=8)
for i in range(50):
thread_pool.submit(search)
thread_pool.shutdown(wait=True)
I tried this with different sync strategies for the connection and it occurred for all of them, even for the thread-safe strategies e.g. SAFE_SYNC. It seems that these strategies are only intended to protect the connection object if it is shared over multiple threads. Is that correct?
A simple solution would be to use the lock also in the read operation of the schema:
@property
def schema(self):
with self.dit_lock:
return self._schema_info
This solved my issue, however I did not test it for other configs.
Am I missing something or is it not intended to share the server object over multiple threads?
The text was updated successfully, but these errors were encountered:
I have multiple threads accessing the same server object. Each thread creates a new connection to the same server. In the search operation, the schema from the server is accessed by the connection.
ldap3/ldap3/core/connection.py
Lines 870 to 882 in 86a9e7a
In the bind operation of a new connection, the server info is refreshed. The schema is temporarily set to
None
before the new schema is set.ldap3/ldap3/core/server.py
Line 498 in 86a9e7a
For the write operation, a lock is used. However, the read operation is not protected. If another thread now reads the schema it is None and the attributes from the search operation can not be decoded properly. The
attributes
dictionary is equal to theraw_attributes
dictionary. For example, uuids are returned in bytes instead of a string.Here is an example to reproduce the behavior:
I tried this with different sync strategies for the connection and it occurred for all of them, even for the thread-safe strategies e.g. SAFE_SYNC. It seems that these strategies are only intended to protect the connection object if it is shared over multiple threads. Is that correct?
A simple solution would be to use the lock also in the read operation of the schema:
This solved my issue, however I did not test it for other configs.
Am I missing something or is it not intended to share the server object over multiple threads?
The text was updated successfully, but these errors were encountered: