promise.wait() in 'connect' event listener

124 views
Skip to first unread message

Christian Joudrey

unread,
Dec 7, 2009, 10:10:01 PM12/7/09
to nodejs
Hello,

I have recently tried to use the wait() method on a dns.reverse call
within a 'connect' event and it leads to the following:

(node) WARNING: promise.wait() is being called too often.
(node) WARNING: promise.wait() is being called too often.
(node) WARNING: promise.wait() is being called too often.
Segmentation fault

Has this happen to anybody? Is there a solution?

Here is a simple example:

var tcp = require("tcp");
var dns = require('dns');
var sys = require('sys');

var server = tcp.createServer(function (socket) {
socket.setEncoding("utf8");

socket.addListener("connect", function () {
socket.send("hello\r\n");

var reverse = dns.reverse(socket.remoteAddress);

reverse.addCallback(function(domains, ttl, cname)
{

});

reverse.addErrback(function()
{

});

reverse.wait();
});

socket.addListener("receive", function (data) {
socket.send(data);
});

socket.addListener("eof", function () {
socket.send("goodbye\r\n");
socket.close();
});
});

server.listen(7000, "localhost");

Ryan Dahl

unread,
Dec 7, 2009, 11:53:28 PM12/7/09
to nod...@googlegroups.com
On Tue, Dec 8, 2009 at 4:10 AM, Christian Joudrey <cmal...@gmail.com> wrote:
> Hello,
>
> I have recently tried to use the wait() method on a dns.reverse call
> within a 'connect' event and it leads to the following:
>
> (node) WARNING: promise.wait() is being called too often.
> (node) WARNING: promise.wait() is being called too often.
> (node) WARNING: promise.wait() is being called too often.

I suspect you're calling wait() too often. wait() is just a hack for
very simple situations and is not mean to be used with-in a busy
process. The documentation says

> IMPORTANT promise.wait() is not a true fiber/coroutine. If any
> other promises are created and made to wait while the first
> promise waits, the first promise’s wait will not return until all others
> return. The benefit of this is a simple implementation and the event
> loop does not get blocked. Disadvantage is the possibility of situations
> where the promise stack grows infinitely large because promises
> keep getting created and keep being told to wait(). Use promise.wait()
> sparingly—probably best used only during program setup, not during
> busy server activity.

Ryan Dahl

unread,
Dec 7, 2009, 11:54:44 PM12/7/09
to nod...@googlegroups.com
> var server = tcp.createServer(function (socket) {
>        socket.setEncoding("utf8");
>
>        socket.addListener("connect", function () {
>                socket.send("hello\r\n");
>
>                var reverse = dns.reverse(socket.remoteAddress);
>
>                reverse.addCallback(function(domains, ttl, cname)
>                {
>
>                });
>
>                reverse.addErrback(function()
>                {
>
>                });
>
>                reverse.wait();
>        });
>

You don't even need wait() here. If you're adding callbacks then
that's enough. Just remove the wait() line.

Christian Joudrey

unread,
Dec 8, 2009, 9:37:24 PM12/8/09
to nodejs
Actually the goal here is to force the server to wait until a response
is given by the dns reverse.

Basically, queuing all events until the DNS is resolved.

The only other way of doing this would be to actually set a variable
"socket.busy = true" and make it queue all onreceive manually until
"busy = false".

I may have misunderstood the point of wait() in this case. I was
actually trying to "block" that specific socket.

Ryan Dahl

unread,
Dec 9, 2009, 12:56:46 AM12/9/09
to nod...@googlegroups.com
On Wed, Dec 9, 2009 at 3:37 AM, Christian Joudrey <cmal...@gmail.com> wrote:
> Actually the goal here is to force the server to wait until a response
> is given by the dns reverse.
>
> Basically, queuing all events until the DNS is resolved.

What about this:

var tcp = require("tcp");
var dns = require('dns');
var sys = require('sys');

var server = tcp.createServer(function (socket) {
socket.setEncoding("utf8");

socket.addListener("connect", function () {
socket.send("hello\r\n");

var reverse = dns.reverse(socket.remoteAddress);

reverse.addCallback(function(domains, ttl, cname)
{
socket.send("your address: " + JSON.stringify(domains) + "\r\n");
});

reverse.addErrback(function()
{
socket.send("error reversing address\r\n");

Christian Joudrey

unread,
Dec 9, 2009, 10:20:08 AM12/9/09
to nod...@googlegroups.com
The idea would be more like:


 var tcp = require("tcp");
 var dns = require('dns');
 var sys = require('sys');

 var server = tcp.createServer(function (socket) {
    socket.setEncoding("utf8");

    socket.addListener("connect", function () {
      socket.wait = true;
      socket.buffer = [];

      socket.send("hello\r\n");

      var reverse = dns.reverse(socket.remoteAddress);

      reverse.addCallback(function(domains, ttl, cname)
      {
        socket.wait = false;
        socket.address = JSON.stringify(domains);

        socket.send("your address: " + JSON.stringify(domains) + "\r\n");

        if (socket.buffer.length > 0)
        {
           // trigger a "receive" events with the buffer data

            for(var i = 0; i < socket.buffer.length; i++)
            {
                // trigger "receive" event with data = socket.buffer[i]
            }

           // empty the buffer
           socket.buffer = [];
        }
      });

      reverse.addErrback(function()
      {
        socket.wait = false;

        socket.send("error reversing address\r\n");
      });
    });

    socket.addListener("receive", function (data) {
      if (socket.wait)
      {
        // we are currently waiting for the DNS to resolve, queue all data
        socket.buffer.push(data);
      }
      else
      {
        // the dns has resolved, proceed to normal parsing...

        socket.send(data);
      }
    });

    socket.addListener("eof", function () {
      socket.send("goodbye\r\n");
      socket.close();
    });
 });

 server.listen(7000, "localhost");

However, I haven't looked into the documentation enough to know if we can trigger events... For example could I trigger the "receive" event of a tcp.connection ?

Again, the idea is to block all further communication until the DNS is resolved.

The client may send data, but we need to queue it and ignore it until the DNS is resolved THEN we can process the previous data.


--

You received this message because you are subscribed to the Google Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com.
To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.



Ryan Dahl

unread,
Dec 10, 2009, 5:02:08 PM12/10/09
to nod...@googlegroups.com
On Wed, Dec 9, 2009 at 4:20 PM, Christian Joudrey <cmal...@gmail.com> wrote:
> The idea would be more like:
>
>  var tcp = require("tcp");
>  var dns = require('dns');
>  var sys = require('sys');
>
>  var server = tcp.createServer(function (socket) {
>     socket.setEncoding("utf8");
>
>     socket.addListener("connect", function () {
>       socket.wait = true;
>       socket.buffer = [];
>       socket.send("hello\r\n");
>
>       var reverse = dns.reverse(socket.remoteAddress);
>
>       reverse.addCallback(function(domains, ttl, cname)
>       {
>         socket.wait = false;
>         socket.address = JSON.stringify(domains);
>         socket.send("your address: " + JSON.stringify(domains) + "\r\n");
>
>         if (socket.buffer.length > 0)
>         {
>            // EDITED HERE
>             while (socket.buffer.length)
>             {
>                 socket.send(socket.buffer.shift());

>             }
>         }
>       });
>
>       reverse.addErrback(function()
>       {
>         socket.wait = false;
>         socket.send("error reversing address\r\n");
>       });
>     });
>
>     socket.addListener("receive", function (data) {
>       if (socket.wait)
>       {
>         // we are currently waiting for the DNS to resolve, queue all data
>         socket.buffer.push(data);
>       }
>       else
>       {
>         // the dns has resolved, proceed to normal parsing...
>         socket.send(data);
>       }
>     });
>
>     socket.addListener("eof", function () {
>       socket.send("goodbye\r\n");
>       socket.close();
>     });
>  });
>
>  server.listen(7000, "localhost");
>
> However, I haven't looked into the documentation enough to know if we can
> trigger events... For example could I trigger the "receive" event of a
> tcp.connection ?

No need to trigger events. The above code should work - that is how
you get the behavior you want. I edited one line.

Reply all
Reply to author
Forward
0 new messages