Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

copas.step() throws error #21

Closed
okroth opened this issue Dec 15, 2014 · 7 comments
Closed

copas.step() throws error #21

okroth opened this issue Dec 15, 2014 · 7 comments

Comments

@okroth
Copy link

okroth commented Dec 15, 2014

According to its documentation in the reference manual, copas.step() should return nil plus error message in case of errors. However, if _select(), which is called by step(), returns anything (else than "timeout") copas.step() calls error() which stops the whle program, as it is difficult to catch this one.
Is this intentional?
Note: errors in the threads itself are handled.

@Tieske
Copy link
Member

Tieske commented Dec 15, 2014

Is this a theoretical question, or did you actually run into this?

In the _select function the error value is received from socket.select, and the LuaSocket docs state;

The error message is "timeout" if a timeout condition was met and nil otherwise.

Deducing from that, the error value cannot be different from timeout unless there is a bug in luasockets code or documentation. But this is the theoretical path...

@okroth
Copy link
Author

okroth commented Dec 15, 2014

Hello Thijs,

unfortunately it is no theory. It is a practical problem. Possibly I
have to consult the LuaSocket implementation vs. documentation as well.
socket.select does return "error".
Nevertheless, I liked to see a nil + "error" returned, not "error"
thrown as such.

I can adjust the behaviour to my personal intention, but certainly there
are smarter configurations, which I don't like to miss.

Oliver

Am 15.12.2014 um 20:26 schrieb Thijs Schreijer:

Is this a theoretical question, or did you actually run into this?

In the |_select| function the error value is received from
|socket.select|, and the LuaSocket docs state;

The error message is "timeout" if a timeout condition was met and
nil otherwise.

Deducing from that, the error value cannot be different from |timeout|
unless there is a bug in luasockets code or documentation. But this is
the theoretical path...


Reply to this email directly or view it on GitHub
#21 (comment).

@Tieske
Copy link
Member

Tieske commented Dec 15, 2014

It is then determined by the reason for the error. That will tell you whether it's a Copas or LuaSocket issue I guess.

@okroth
Copy link
Author

okroth commented Dec 16, 2014

Looks as if there is a discrepancy between socket.select's documentation and implementation. It indeed returns the string "error" and not the value nil.
I will knock at socket's door then...

@okroth
Copy link
Author

okroth commented Dec 17, 2014

I found that there is an error in LuaSocket's implementation / documentation.
However, the error seems to be induced by an oddity in Copas, within the copas.connect() method. It calls socket:connect() more than once, which on some (at least one - my one) operating system let it return with an error indicating that it is already busy. And this let finally copas.step() tip over.
So the problem is now in copas.connect(). POSIX says this about connect() with non-blocking sockets:
"If the connection cannot be established immediately and O_NONBLOCK is set for the file descriptor for the socket, connect() shall fail and set errno to [EINPROGRESS], but the connection request shall not be aborted, and the connection shall be established asynchronously. Subsequent calls to connect() for the same socket, before the connection is established, shall fail and set errno to [EALREADY]."
So to me the method to re-call connect in the copas.connect() method seems to be non-standard.

Most examples, including that on pages 448ff of the book "UNIX Network Programming" by W. Richard Stevens, use select() to wait for the socket becoming writeable and then use getsockopt( ..., SOL_SOCKET, SO_ERROR,...) to retrieve the outcome of connect().

However... LuaSockets 2.0.2 does not document tcp.getoption(), (LuaSocket 3.0 does), but getting the SO_ERROR is not implemented at all. So, for a full implementation, LuaSocket has to be changed.

I found that in many implementations people just wait for the socket to become writeable, and then rely on getting an error on using it when it is not actually connected.

Would this be an option for copas.connect() ?

@okroth
Copy link
Author

okroth commented Dec 21, 2014

Update...
I found that your method to call connect() again, may work on many systems; however, LuaSockets (i.e. usocket.c 's socket_connect() ) has a little bug to test on EAGAIN instead EALREADY when it is called again. This way it misses the opportunity to return "timeout" in that case.
This spoils the probing that copas.connect() uses.
BTW: The wsocket.c socket_connect() also misses one return value: WSAEINVAL, which may be returned as compatibilty option...

@Tieske
Copy link
Member

Tieske commented Mar 5, 2015

fixed in #25 throwing an error was not correct. Docs tell that step returns nil + error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants