jeremycx / node-LDAP

LDAP binding for node.js
MIT License
221 stars 43 forks source link

Node Crash #90

Open imperugo opened 8 years ago

imperugo commented 8 years ago

Hi, I'm having a strange problem with your library. Basically sometimes (it seems random) calling a search command I've the following error:

debug: Getting users from LDAP
node: ../deps/uv/src/unix/core.c:864: uv__io_stop: Assertion `loop->watchers[w->fd] == w' failed.
Aborted (core dumped)

I've enabled the debug mode on your library and here the output

debug: Getting users from LDAP
ldap_simple_bind
ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP topolino.gaia.is.it:389
ldap_new_socket: 14
ldap_prepare_socket: 14
ldap_connect_to_host: Trying 192.168.16.60:389
ldap_pvt_connect: fd: 14 tm: 1 async: 0
ldap_ndelay_on: 14
attempting to connect:
connect errno: 115
ldap_int_poll: fd: 14 tm: 1
ldap_is_sock_ready: 14
ldap_ndelay_off: 14
ldap_pvt_connect: 0
node: ../deps/uv/src/unix/core.c:864: uv__io_stop: Assertion `loop->watchers[w->fd] == w' failed.
./prod-test.sh: line 9: 24604 Aborted                 (core dumped) node ./build/app.js

It happens both on OSX and Ubuntu Server. Here the code I use to call ldap server (it's Typescript).

constructor() {
        this.ldapClient = new LdapClient({
            uri: ldapConfiguration.serverUrl,
            version: 3,
            connecttimeout: -1,
            base: ldapConfiguration.searchBaseUsers,
            validatecert: false,
            // debug: 255,
            attrs: "memberof uid gecos displayName mail departmentNumber employeeNumber mobile postalAddress telephoneNumber title",
        });
    }

public getUsers(department: string): Promise<User[]> {
        this.logger.debug("Getting users from LDAP");

        let filter: any;

        if (department) {
            filter = LdapClient.escapefn("filter", "(&(departmentNumber=%s)(objectClass=posixAccount)(!(uid=admin)))")(department);
        } else {
            filter = LdapClient.escapefn("filter", "(&(objectClass=posixAccount)(!(uid=admin)))")();
        }

        return new Promise<User[]>((resolve, reject) => {
            this.ldapClient.bind({
                binddn: ldapConfiguration.bindDomain,
                password: ldapConfiguration.bindPassword,
            }, (err: any) => {
                if (err) {
                    this.logger.error(err);
                    return reject(err);
                }

                this.logger.debug("Calling LDAP for search users");

                this.ldapClient.search({
                    filter: filter,
                    base: ldapConfiguration.searchBaseUsers,
                    scope: LdapClient.SUBTREE,
                }, (error: any, data: any) => {
                    if (error) {
                        this.logger.error("LDAP request fro search users failed, " + error);
                        return reject(error);
                    }

                    let result = new Array<User>();

                    if (data.length < 1) {
                        this.logger.debug("Users not found.");
                        return resolve(result);
                    }

                    this.logger.debug("Users found. ", data);

                    for (let element of data) {
                        result.push(new User(element));
                    }

                    return resolve(result);
                });
            });
        });
    }

It happens with Node 4.x, 5.x and 6.x.

Any hint?

jeremycx commented 8 years ago

I'm suspicious of Promises. Can you verify that there is no crash when it's not wrapped in a promise?

imperugo commented 8 years ago

I was thinking the same, but it seems is not related to the promise. I switched the code to ldapjs and it seems to work

jeremycx commented 8 years ago

ldapjs is a very different beast, it's all javascript-native (and they did a great job of it too).

How did you determine that it isn't related to promises?

imperugo commented 8 years ago

because I used the same code without the promise and I got the same error

jeremycx commented 8 years ago

Can you please post that code, too?

604bpierce commented 7 years ago

I too am getting this issue, seemingly randomly. I have not yet seen any pattern on the appearance of this bug.

Edit: I should mention: When using bind() the error is:

node: ../deps/uv/src/unix/core.c:888: uv__io_stop: Assertion `loop->watchers[w->fd] == w' failed.
Aborted (core dumped)

When using findandbind() the error is:

Aborted (core dumped)
604bpierce commented 7 years ago

I stand corrected, just had the following output from findandbind() attempt:

node: ../deps/uv/src/unix/core.c:888: uv__io_stop: Assertion `loop->watchers[w->fd] == w' failed.
Aborted (core dumped)
1964Simon commented 5 years ago

Same Issue in my applicaton. ../deps/uv/src/unix/core.c:878: uv__io_stop: Assertionloop->watchers[w->fd] == w' failed.` Node Version v11.9.0

Code: get_contacts: function (req, res) { ldap.bind(user, function (err) { console.log("Error", err); var search_options = { base: "OU=X,OU=X,DC=X,DC=X,DC=X", scope: LDAP.SUBTREE, filter: '(objectClass=contact)', attrs: '*' } ldap.search(search_options, function (err, data) { var data1 = data.map(obj => { for (var key in obj) { if (Array.isArray(obj[key])) { obj[key] = obj[key][0]; } } return obj; }); res.status(200).json(data1); }); }); },

pfree commented 4 years ago

I was experiencing this same crash on 3.1.3 (49bf193) running node v8.14.0.

The problem is that the module is re-using the handle. In the OnDisconnect callback, it calls uv_poll_stop to stop watching the handle. Later, in OnConnect, it sees that the handle is non-NULL and calls uv_poll_stop again.

We were able to fix this by setting the handle to NULL in OnDisconnect.

Patch

diff --git a/LDAPCnx.cc b/LDAPCnx.cc
index 532317f..8325a78 100644
--- a/LDAPCnx.cc
+++ b/LDAPCnx.cc
@@ -219,6 +219,7 @@ void LDAPCnx::OnDisconnect(LDAP *ld, Sockbuf *sb,
   LDAPCnx * lc = (LDAPCnx *)ctx->lc_arg;
   if (lc->handle) {
     uv_poll_stop(lc->handle);
+    lc->handle=NULL;
   }
   lc->disconnect_callback->Call(0, NULL);
 }

Backtrace

#0  0x00007f2739af6e97 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007f2739af8801 in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007f2739ae839a in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x00007f2739ae8412 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6
#4  0x000055e58cf29849 in uv__io_stop (loop=<optimized out>, w=w@entry=0x55e58ee94688, events=events@entry=8199) at ../deps/uv/src/unix/core.c:898
#5  0x000055e58cf302f4 in uv__poll_stop (handle=0x55e58ee94620) at ../deps/uv/src/unix/poll.c:103
#6  uv_poll_stop (handle=0x55e58ee94620) at ../deps/uv/src/unix/poll.c:113
#7  0x00007f27345b538b in LDAPCnx::OnConnect (ld=0x55e58ef019f0, sb=<optimized out>, srv=<optimized out>, addr=<optimized out>, ctx=<optimized out>) at ../LDAPCnx.cc:207
#8  0x00007f2734386cf5 in ldap_int_connect_cbs () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#9  0x00007f2734386fdc in ldap_connect_to_host () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#10 0x00007f273436f0de in ldap_int_open_connection () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#11 0x00007f273438434d in ldap_new_connection () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#12 0x00007f273436e74a in ldap_open_defconn () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#13 0x00007f2734385908 in ldap_send_initial_request () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#14 0x00007f2734378b8f in ldap_sasl_bind () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#15 0x00007f273437adc2 in ldap_simple_bind () from /usr/lib/x86_64-linux-gnu/libldap_r-2.4.so.2
#16 0x00007f27345b62db in LDAPCnx::Bind (info=...) at /home/gitlab-runner/.cache/node-gyp/8.14.0/include/node/v8.h:9761
#17 0x00007f27345b515f in Nan::imp::FunctionCallbackWrapper (info=...) at ../../nan/nan_callbacks_12_inl.h:174
#18 0x000055e58d017849 in v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) ()
#19 0x000055e58d095a6e in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) ()
#20 0x000055e58d096941 in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) ()