[erlang-bugs] : : : : : Follow up: [BUG] gen_tcp:connect/3, 4 returns socket for closed port
Raimo Niskanen
raimo+erlang-bugs@REDACTED
Tue Sep 16 09:22:05 CEST 2008
On Mon, Sep 15, 2008 at 11:17:42AM -0400, Edwin Fine wrote:
> Raimo,
>
> Great work! You found it pretty quickly. I'll apply the patch as soon as
> possible.
> I'll wait for a while before applying the patch to production systems until
> the regression tests are done.
We found no problems with this patch in the regression tests.
Now we will see what you and the other users find...
>
> Thanks very much.
> Regards,
> Edwin Fine
>
> On Mon, Sep 15, 2008 at 10:54 AM, Raimo Niskanen <
> raimo+erlang-bugs@REDACTED <raimo%2Berlang-bugs@REDACTED>>wrote:
>
:
> > Found the bug!
> >
> > It was a clear and simple bug in the TCP|UDP|SCTP/IP driver
> > inet_drv, where making a connect, the poll set was changed
> > first and then connect was called, and if connect did
> > not give EINPROGRESS, the poll set was reset again.
> >
> > This is the wrong way to do it. The right is to change
> > the poll set if you have to after getting EINPROGRESS.
> >
> > What happened now was:
> > [thread 1] [thread 2]
> >
> > poll( ...
> > socket() -> Socket
> > Change pollset data
> > write(InternalPipe)
> > to inform poll thread
> > ...)poll -> internal pipe POLLIN|POLLRDNORM
> > read(InternalPipe)
> > connect(Socket, ...
> > poll() -> Socket POLLOUT|POLLHUP
> > ... )connect -> EINPROGRESS
> > getsockopt(Socket, SOL_SOCKET, SO_ERROR) ->
> > no error
> >
> > Note that poll returns with ready for writing on Socket
> > before connect returns with EINPROGRESS in the other
> > thread, and Linus only knows why getsockopt() in this
> > particular case returns no error.
> >
> > But we are mishandling the socket, that is for sure.
> > Try this patch:
> > *** /clearcase/otp/erts/erts/emulator/drivers/common/inet_drv.c@@/OTP_R12B-4
> > 2008-09-01 14:51:18.000000000 +0200
> > --- /clearcase/otp/erts/erts/emulator/drivers/common/inet_drv.c 2008-09-15
> > 16:23:51.000000000 +0200
> > ***************
> > *** 7239,7257 ****
> > buf, &len) == NULL)
> > return ctl_error(EINVAL, rbuf, rsize);
> >
> > - sock_select(INETP(desc), FD_CONNECT, 1);
> > code = sock_connect(desc->inet.s,
> > (struct sockaddr*) &desc->inet.remote, len);
> > if ((code == SOCKET_ERROR) &&
> > ((sock_errno() == ERRNO_BLOCK) || /* Winsock2 */
> > (sock_errno() == EINPROGRESS))) { /* Unix & OSE!! */
> > desc->inet.state = TCP_STATE_CONNECTING;
> > if (timeout != INET_INFINITY)
> > driver_set_timer(desc->inet.port, timeout);
> > enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
> > }
> > else if (code == 0) { /* ok we are connected */
> > - sock_select(INETP(desc), FD_CONNECT, 0);
> > desc->inet.state = TCP_STATE_CONNECTED;
> > if (desc->inet.active)
> > sock_select(INETP(desc), (FD_READ|FD_CLOSE), 1);
> > --- 7239,7256 ----
> > buf, &len) == NULL)
> > return ctl_error(EINVAL, rbuf, rsize);
> >
> > code = sock_connect(desc->inet.s,
> > (struct sockaddr*) &desc->inet.remote, len);
> > if ((code == SOCKET_ERROR) &&
> > ((sock_errno() == ERRNO_BLOCK) || /* Winsock2 */
> > (sock_errno() == EINPROGRESS))) { /* Unix & OSE!! */
> > + sock_select(INETP(desc), FD_CONNECT, 1);
> > desc->inet.state = TCP_STATE_CONNECTING;
> > if (timeout != INET_INFINITY)
> > driver_set_timer(desc->inet.port, timeout);
> > enq_async(INETP(desc), tbuf, INET_REQ_CONNECT);
> > }
> > else if (code == 0) { /* ok we are connected */
> > desc->inet.state = TCP_STATE_CONNECTED;
> > if (desc->inet.active)
> > sock_select(INETP(desc), (FD_READ|FD_CLOSE), 1);
> > ***************
> > *** 7259,7265 ****
> > async_ok(INETP(desc));
> > }
> > else {
> > - sock_select(INETP(desc), FD_CONNECT, 0);
> > return ctl_error(sock_errno(), rbuf, rsize);
> > }
> > return ctl_reply(INET_REP_OK, tbuf, 2, rbuf, rsize);
> > --- 7258,7263 ----
> >
> > The patch has not been run through all our regression tests yet.
> >
> > --
> >
> > / Raimo Niskanen, Erlang/OTP, Ericsson AB
> >
> >
--
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
More information about the erlang-bugs
mailing list