Erlang Mailing Lists

Author Message

<  Erlang patches mailing list  ~  [PATCH] Exit if an error occurs with the listening socket

Guest
Posted: Sun Mar 21, 2010 1:30 am Reply with quote
Guest
On erlang-questions, there was a thread about epmd consuming 100% CPU
under some conditions:

http://www.erlang.org/cgi-bin/ezmlm-cgi?4:mss:50068:ikpcjohfehcpniapmcfm

Looking through the code for epmd_srv.c, when either select() or accept()
returns an error, errno is not checked. In the case of an error with
the socket, this will cause select/accept to return immediately and loop.

The easiest way of reproducing this situation is by using too many
file descriptors:

http://gist.github.com/338996

In one shell:

$ ulimit -n 16
$ epmd -d -port 1234

In another shell:

$ erl
$ emfile:start(1234,32).

epmd will log many errors and consume CPU:

epmd: Sat Mar 20 20:09:45 2010: error in accept: Too many open files

Since my github fork is "temporarily unavailable", the patch will be
sent separately in git patch format. If the patch needs to be re-worked,
please let me know, and I will do so when my fork is back up.




________________________________________________________________
erlang-patches (at) erlang.org mailing list.
See http://www.erlang.org/faq.html
To unsubscribe; mailto:erlang-patches-unsubscribe@erlang.org

Post received from mailinglist
Guest
Posted: Sun Mar 21, 2010 1:30 am Reply with quote
Guest
On erlang-questions, there was a thread about epmd consuming 100% CPU
under some conditions:

http://www.erlang.org/cgi-bin/ezmlm-cgi?4:mss:50068:ikpcjohfehcpniapmcfm

Looking through the code for epmd_srv.c, when either select() or accept()
returns an error, errno is not checked. In the case of an error with
the socket, this will cause select/accept to return immediately and loop.

The easiest way of reproducing this situation is by using too many
file descriptors:

http://gist.github.com/338996

In one shell:

$ ulimit -n 16
$ epmd -d -port 1234

In another shell:

$ erl
$ emfile:start(1234,32).

epmd will log many errors and consume CPU:

epmd: Sat Mar 20 20:09:45 2010: error in accept: Too many open files

Since my github fork is "temporarily unavailable", the patch will be
sent separately in git patch format. If the patch needs to be re-worked,
please let me know, and I will do so when my fork is back up.




________________________________________________________________
erlang-patches (at) erlang.org mailing list.
See http://www.erlang.org/faq.html
To unsubscribe; mailto:erlang-patches-unsubscribe@erlang.org

Post received from mailinglist
Guest
Posted: Sun Mar 21, 2010 1:31 am Reply with quote
Guest
Check errno if either select() or accept() returns an error and exit.
This prevents epmd from looping and taking up 100% CPU.
---
erts/epmd/src/epmd_srv.c | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index a033fab..7e4a661 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -227,8 +227,16 @@ void run(EpmdVars *g)
timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT;
timeout.tv_usec = 0;

- if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0)
+ if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0) {
dbg_perror(g,"error in select ");
+ switch (errno) {
+ case EAGAIN:
+ case EINTR:
+ break;
+ default:
+ epmd_cleanup_exit(g,1);
+ }
+ }
else {
time_t now;
if (ret == 0) {
@@ -401,7 +409,14 @@ static int do_accept(EpmdVars *g,int listensock)

if (msgsock < 0) {
dbg_perror(g,"error in accept");
- return EPMD_FALSE;
+ switch (errno) {
+ case EAGAIN:
+ case ECONNABORTED:
+ case EINTR:
+ return EPMD_FALSE;
+ default:
+ epmd_cleanup_exit(g,1);
+ }
}

return conn_open(g,msgsock);
--
1.5.4.3


________________________________________________________________
erlang-patches (at) erlang.org mailing list.
See http://www.erlang.org/faq.html
To unsubscribe; mailto:erlang-patches-unsubscribe@erlang.org

Post received from mailinglist
Guest
Posted: Sun Mar 21, 2010 1:31 am Reply with quote
Guest
Check errno if either select() or accept() returns an error and exit.
This prevents epmd from looping and taking up 100% CPU.
---
erts/epmd/src/epmd_srv.c | 19 +++++++++++++++++--
1 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
index a033fab..7e4a661 100644
--- a/erts/epmd/src/epmd_srv.c
+++ b/erts/epmd/src/epmd_srv.c
@@ -227,8 +227,16 @@ void run(EpmdVars *g)
timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT;
timeout.tv_usec = 0;

- if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0)
+ if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0) {
dbg_perror(g,"error in select ");
+ switch (errno) {
+ case EAGAIN:
+ case EINTR:
+ break;
+ default:
+ epmd_cleanup_exit(g,1);
+ }
+ }
else {
time_t now;
if (ret == 0) {
@@ -401,7 +409,14 @@ static int do_accept(EpmdVars *g,int listensock)

if (msgsock < 0) {
dbg_perror(g,"error in accept");
- return EPMD_FALSE;
+ switch (errno) {
+ case EAGAIN:
+ case ECONNABORTED:
+ case EINTR:
+ return EPMD_FALSE;
+ default:
+ epmd_cleanup_exit(g,1);
+ }
}

return conn_open(g,msgsock);
--
1.5.4.3


________________________________________________________________
erlang-patches (at) erlang.org mailing list.
See http://www.erlang.org/faq.html
To unsubscribe; mailto:erlang-patches-unsubscribe@erlang.org

Post received from mailinglist
Guest
Posted: Tue Mar 30, 2010 1:32 pm Reply with quote
Guest
On Tue, Mar 30, 2010 at 11:58:48AM +0200, Bj??rn Gustavsson wrote:
> 2010/3/22 Bj??rn Gustavsson <bgustavsson@gmail.com>:
> > On Sun, Mar 21, 2010 at 2:30 AM, Michael Santos
> > <michael.santos@gmail.com> wrote:
> >> Check errno if either select() or accept() returns an error and exit.
> >> This prevents epmd from looping and taking up 100% CPU.
> >
> > Thanks! Will include in 'pu'.
>
> I did not build on Windows. I have added an additional
> commit that fixes that. I intend to squash that commit into
> your commit if/when the branch is graduated.
>
> Are there other platforms that don't have ECONNABORTED
> defined?

Yay, I broke the Windows build! Wink Thanks for fixing the patch.

Looking through erts/emulator/drivers/common/inet_drv.c, the only platform
for which ECONNABORTED is explicitly handled is Windows:

#ifdef __WIN32__
#define ECONNABORTED WSAECONNABORTED
#endif /* __WIN32__ */


> diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
> index 7e4a661..83ebdaa 100644
> --- a/erts/epmd/src/epmd_srv.c
> +++ b/erts/epmd/src/epmd_srv.c
> @@ -411,7 +411,9 @@ static int do_accept(EpmdVars *g,int listensock)
> dbg_perror(g,"error in accept");
> switch (errno) {
> case EAGAIN:
> +#ifndef __WIN32__
> case ECONNABORTED:
> +#endif
> case EINTR:
> return EPMD_FALSE;
> default:



________________________________________________________________
erlang-patches (at) erlang.org mailing list.
See http://www.erlang.org/faq.html
To unsubscribe; mailto:erlang-patches-unsubscribe@erlang.org

Post received from mailinglist
Guest
Posted: Tue Mar 30, 2010 1:32 pm Reply with quote
Guest
On Tue, Mar 30, 2010 at 11:58:48AM +0200, Bj??rn Gustavsson wrote:
> 2010/3/22 Bj??rn Gustavsson <bgustavsson@gmail.com>:
> > On Sun, Mar 21, 2010 at 2:30 AM, Michael Santos
> > <michael.santos@gmail.com> wrote:
> >> Check errno if either select() or accept() returns an error and exit.
> >> This prevents epmd from looping and taking up 100% CPU.
> >
> > Thanks! Will include in 'pu'.
>
> I did not build on Windows. I have added an additional
> commit that fixes that. I intend to squash that commit into
> your commit if/when the branch is graduated.
>
> Are there other platforms that don't have ECONNABORTED
> defined?

Yay, I broke the Windows build! Wink Thanks for fixing the patch.

Looking through erts/emulator/drivers/common/inet_drv.c, the only platform
for which ECONNABORTED is explicitly handled is Windows:

#ifdef __WIN32__
#define ECONNABORTED WSAECONNABORTED
#endif /* __WIN32__ */


> diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c
> index 7e4a661..83ebdaa 100644
> --- a/erts/epmd/src/epmd_srv.c
> +++ b/erts/epmd/src/epmd_srv.c
> @@ -411,7 +411,9 @@ static int do_accept(EpmdVars *g,int listensock)
> dbg_perror(g,"error in accept");
> switch (errno) {
> case EAGAIN:
> +#ifndef __WIN32__
> case ECONNABORTED:
> +#endif
> case EINTR:
> return EPMD_FALSE;
> default:



________________________________________________________________
erlang-patches (at) erlang.org mailing list.
See http://www.erlang.org/faq.html
To unsubscribe; mailto:erlang-patches-unsubscribe@erlang.org

Post received from mailinglist

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum