diff --git a/deps/libeio/xthread.h b/deps/libeio/xthread.h index e53cb53da8..c39d39d47e 100644 --- a/deps/libeio/xthread.h +++ b/deps/libeio/xthread.h @@ -127,8 +127,10 @@ thread_create (thread_t *tid, void *(*proc)(void *), void *arg) pthread_attr_init (&attr); pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096 ? sizeof (long) * 4096 : PTHREAD_STACK_MIN); + */ #ifdef PTHREAD_SCOPE_PROCESS pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS); #endif diff --git a/src/net.cc b/src/net.cc index 28a24c4aa6..b718d9139b 100644 --- a/src/net.cc +++ b/src/net.cc @@ -5,22 +5,28 @@ #include #include +#include +#include +#include + #include #include #include -#include using namespace v8; -static struct addrinfo tcp_hints = +#define ON_CONNECT_SYMBOL String::NewSymbol("onConnect") +#define ON_READ_SYMBOL String::NewSymbol("onRead") + +static const struct addrinfo tcp_hints = /* ai_flags */ { AI_PASSIVE /* ai_family */ , AF_UNSPEC /* ai_socktype */ , SOCK_STREAM /* ai_protocol */ , 0 /* ai_addrlen */ , 0 -/* ai_addr */ , 0 -/* ai_canonname */ , 0 -/* ai_next */ , 0 +/* ai_addr */ , NULL +/* ai_canonname */ , NULL +/* ai_next */ , NULL }; @@ -44,12 +50,18 @@ public: static void OnClose (oi_socket *s); static void OnTimeout (oi_socket *s); + char *host_; + char *port_; + private: + static int Resolve (eio_req *req); + static int AfterResolve (eio_req *req); + static Socket* Unwrap (Handle handle); static void MakeWeak (Persistent _, void *data); + enum {UTF8, RAW} encoding_; oi_socket socket_; - struct addrinfo *address_; Persistent handle_; }; @@ -112,35 +124,81 @@ Socket::ConnectTCP (const Arguments& args) Socket *socket = Socket::Unwrap(args.Holder()); String::AsciiValue port(args[0]); + socket->port_ = strdup(*port); char *host = NULL; String::AsciiValue host_v(args[1]->ToString()); if(args[1]->IsString()) { - host = *host_v; + socket->host_ = strdup(*host_v); } - int r; + if(args[2]->IsFunction()) { + socket->handle_->Set(ON_CONNECT_SYMBOL , args[2]); + } + + /* For the moment I will do DNS lookups in the thread pool. This is + * sub-optimal and cannot handle massive numbers of requests but it is + * quite portable. + * In the future I will move to a system using adns or udns: + * http://lists.schmorp.de/pipermail/libev/2009q1/000632.html + */ + node_eio_warmup(); + eio_req *req = eio_custom (Socket::Resolve, EIO_PRI_DEFAULT, Socket::AfterResolve, socket); +} + +/* This function is executed in the thread pool. It cannot touch anything! */ +int +Socket::Resolve (eio_req *req) +{ + Socket *socket = static_cast (req->data); + struct addrinfo *address = NULL; + + req->result = getaddrinfo(socket->host_, socket->port_, &tcp_hints, &address); + + req->ptr2 = address; + + free(socket->host_); + socket->host_ = NULL; + + free(socket->port_); + socket->port_ = NULL; + + return 0; +} + +int +Socket::AfterResolve (eio_req *req) +{ + Socket *socket = static_cast (req->data); + struct addrinfo *address = static_cast(req->ptr2); - /* FIXME Blocking DNS resolution. */ - printf("resolving host: %s, port: %s\n", host, *port); - r = getaddrinfo (host, *port, &tcp_hints, &socket->address_); - if(r != 0) { - perror("getaddrinfo"); - return Undefined(); + int r = 0; + if (req->result == 0) { + r = oi_socket_connect (&socket->socket_, address); } + freeaddrinfo(address); // this was allocated in the thread pool - r = oi_socket_connect (&socket->socket_, socket->address_); - if(r != 0) { - perror("oi_socket_connect"); - return Undefined(); + // no error. return. + if(r == 0 && req->result == 0) { + oi_socket_attach (&socket->socket_, node_loop()); + return 0; } - oi_socket_attach (&socket->socket_, node_loop()); - freeaddrinfo(socket->address_); - socket->address_ = NULL; - // TODO raise error if r != 0 - - return Undefined(); + HandleScope scope; + Handle onconnect_value = socket->handle_->Get(ON_READ_SYMBOL); + if (!onconnect_value->IsFunction()) return 0; + Handle onconnect = Handle::Cast(onconnect_value); + + TryCatch try_catch; + const int argc = 1; + Local argv[argc]; + argv[0] = Integer::New(r | req->result); // FIXME very stupid error code. + + onconnect->Call(socket->handle_, argc, argv); + if(try_catch.HasCaught()) + node_fatal_exception(try_catch); + + return 0; } Handle @@ -176,12 +234,16 @@ Socket::Socket(Handle handle, double timeout) handle_.MakeWeak (this, Socket::MakeWeak); encoding_ = UTF8; + host_ = NULL; + port_ = NULL; } Socket::~Socket () { oi_socket_close(&socket_); oi_socket_detach(&socket_); + free(host_); + free(port_); handle_.Dispose(); handle_.Clear(); // necessary? } @@ -230,14 +292,17 @@ Socket::OnConnect (oi_socket *s) HandleScope scope; - Handle on_connect_value = socket->handle_->Get( String::NewSymbol("onConnect") ); + Handle on_connect_value = socket->handle_->Get(ON_CONNECT_SYMBOL); if (!on_connect_value->IsFunction()) return; Handle on_connect = Handle::Cast(on_connect_value); TryCatch try_catch; + const int argc = 1; + Local argv[argc]; + argv[0] = Integer::New(0); - Handle r = on_connect->Call(socket->handle_, 0, NULL); + Handle r = on_connect->Call(socket->handle_, argc, argv); if(try_catch.HasCaught()) node_fatal_exception(try_catch); @@ -249,7 +314,7 @@ Socket::OnRead (oi_socket *s, const void *buf, size_t count) Socket *socket = static_cast (s->data); HandleScope scope; - Handle onread_value = socket->handle_->Get( String::NewSymbol("onRead") ); + Handle onread_value = socket->handle_->Get(ON_READ_SYMBOL); if (!onread_value->IsFunction()) return; Handle onread = Handle::Cast(onread_value); @@ -306,13 +371,13 @@ Socket::OnDrain (oi_socket *s) Socket *socket = static_cast (s->data); HandleScope scope; - Handle onclose_value = socket->handle_->Get( String::NewSymbol("onDrain") ); - if (!onclose_value->IsFunction()) return; - Handle onclose = Handle::Cast(onclose_value); + Handle ondrain_value = socket->handle_->Get( String::NewSymbol("onDrain") ); + if (!ondrain_value->IsFunction()) return; + Handle ondrain = Handle::Cast(ondrain_value); TryCatch try_catch; - Handle r = onclose->Call(socket->handle_, 0, NULL); + Handle r = ondrain->Call(socket->handle_, 0, NULL); if(try_catch.HasCaught()) node_fatal_exception(try_catch); @@ -325,13 +390,13 @@ Socket::OnError (oi_socket *s, oi_error e) Socket *socket = static_cast (s->data); HandleScope scope; - Handle onclose_value = socket->handle_->Get( String::NewSymbol("onError") ); - if (!onclose_value->IsFunction()) return; - Handle onclose = Handle::Cast(onclose_value); + Handle onerror_value = socket->handle_->Get( String::NewSymbol("onError") ); + if (!onerror_value->IsFunction()) return; + Handle onerror = Handle::Cast(onerror_value); TryCatch try_catch; - Handle r = onclose->Call(socket->handle_, 0, NULL); + Handle r = onerror->Call(socket->handle_, 0, NULL); if(try_catch.HasCaught()) node_fatal_exception(try_catch); @@ -343,13 +408,13 @@ Socket::OnTimeout (oi_socket *s) Socket *socket = static_cast (s->data); HandleScope scope; - Handle onclose_value = socket->handle_->Get( String::NewSymbol("onTimeout") ); - if (!onclose_value->IsFunction()) return; - Handle onclose = Handle::Cast(onclose_value); + Handle ontimeout_value = socket->handle_->Get( String::NewSymbol("onTimeout") ); + if (!ontimeout_value->IsFunction()) return; + Handle ontimeout = Handle::Cast(ontimeout_value); TryCatch try_catch; - Handle r = onclose->Call(socket->handle_, 0, NULL); + Handle r = ontimeout->Call(socket->handle_, 0, NULL); if(try_catch.HasCaught()) node_fatal_exception(try_catch); diff --git a/src/node.cc b/src/node.cc index 1b73a34adf..7a1c1148f9 100644 --- a/src/node.cc +++ b/src/node.cc @@ -156,11 +156,6 @@ thread_pool_want_poll (void) ev_async_send(EV_DEFAULT_ &thread_pool_watcher); } -static void -thread_pool_done_poll (void) -{ -} - void node_eio_warmup (void) { diff --git a/wscript b/wscript index dc33171178..906e193a0c 100644 --- a/wscript +++ b/wscript @@ -63,8 +63,8 @@ def configure(conf): # Configure default variant conf.setenv('default') - conf.env.append_value('CCFLAGS', ['-DNDEBUG', '-O2']) - conf.env.append_value('CXXFLAGS', ['-DNDEBUG', '-O2']) + conf.env.append_value('CCFLAGS', ['-DNDEBUG', '-O2', '-g']) + conf.env.append_value('CXXFLAGS', ['-DNDEBUG', '-O2', '-g']) conf.write_config_header("config.h") def build(bld):