Open WhileLoop opened 2 years ago
I wonder if you have a similar issue as https://github.com/go-ldap/ldap/issues/363 by using Start()
I can reproduce this. I created a an OpenLDAP instance in verbose mode and both search requests were submitted successfully + looking at the package dump in Wireshark, the directory server answered with all the result we're looking for.
It really looks like that spawning a new reader
and processMessage
through conn.Start()
seems to trigger weird behaivour and sometimes even race conditions. I ran the same code 1000 times and the results were almost always different..
I'll take a look at this once I'm home
The problem seems to come from those two lines. One goroutine unregisters the *messageContext
from the map messageContexts
, while the other has still responses in it's pipeline. After unregistering, the pending results are discarded in line 510 & 511. It's basically a race condition that sometimes works, if the goroutine with the response messages is faster -- which isn't possible as soon as the directory server returns a bunch of search results for the library to process..
The question is, why is conn.Start()
exposed in the first place? 😅 Should we perhaps mark it as deprecated and make it private in future versions? I don't see an "easy" way to fix this, since no goroutine can know/guarantee that no packets or responses are pending. If we can't make it private, one way might be to explicitly assign the messageContext to a goroutine so that only one routine ever handles the message for a messageContext.
@vetinari Any thoughts? ^^
I think it's reasonable to either deprecate it and remove it within 12 months (regardless of a major bump or not) or to just remove it. Unless there is something documented that it's intended to be used, or there is a use case linked to its inclusion it should be managed by the library.
hi! Looking at the issue, I can see:
l, err := ldap.DialURL(ldapURL)
if err != nil {
return err
}
l.Start()
however, the "DialURL" function already calls "Start". So, I think you're starting twice the go routines to read replies and process messages, which could cause race condition.
I would not deprecate Connection.Start because some cases you may want to re-use a previously open TCP or TLS connection with this ldap library by "ldap.NewConn" and then you need the "Connection.Start". I like this flexibility. Maybe worth just add a piece of text to the Start and Dial documentation for the users.
I'm going to revert the commit as mentioned in #507 but add a warning to the comment in the meantime. We'll have to either extend our currently available DialOpts or refactor message handling, to bind a messageID to a certain worker to prevent said race conditions
I have encountered a situation where using the search filter
(&(objectClass=inetOrgPerson)(uid=user01))
in go-ldap returns no results but when I search with(objectClass=*)
I can see that the object exists.Using
ldapsearch
with(&(objectClass=inetOrgPerson)(uid=user01))
returns the expected result.My LDAP server is Bitnami OpenLDAP docker image. To reproduce:
docker-compose.yml
program.go
program output:
ldapsearch test:
Full repo: https://github.com/WhileLoop/go-ldap-test