Discussion:
[Wt-interest] Silent failure of server start-up? WServer error handling
K. Frank
2016-10-31 13:23:55 UTC
Permalink
Hello List!

I have two questions about WServer error handling:

(This is wt-3.3.3 compiled with mingw-w64 on windows 7.)

First, I see no errors when trying to start a wthttpd server on an
already bound port. What behavior should I expect?

Details: I've built a "minimal" wthttpd server -- it just servers
html files, so no WApplication. I run two copies of it at the
same time, both launched with "--http-port=80". The first
copy works, services http connections, and serves the html
pages. The second copy reports no errors, and doesn't receive
any http requests -- presumably because all of the port-80 traffic
goes to the first copy.

My understanding is that the first copy binds to port 80, and
everything works. I would expect that the second copy fails
to bind to port 80, which would seem to be to be an error
condition. But the second copy reports no errors.

Here is the relevant code:

int main (int argc, char *argv[]) {
try {
WServer server;
server.setServerConfiguration (argc, argv);
if (server.start()) WServer::waitForShutdown();
else cout << "error on server.start()" << endl;
}
catch (const WException& e) {
cout << "WException caught, e.whatA() = " << e.what() << endl;
}
return 0;
}

Here's how I launch both copies:

minimal_wt3 --http-address=0.0.0.0 --http-port=80
--deploy-path=/dummy --docroot=.

A little more detail: If I kill the first copy of the wthttpd server (and
just leave the second running, without restarting it or anything), the
second copy now responds to incoming connections, serves the
html pages, etc. Is this expected?

Here;s the output from the second copy:

Option no-compression is implied because wthttp was built without
zlib support.
[2016-Oct-31 08:21:09.352845] 4236 - [info] "config: reading Wt
config file: c:/witty/wt_config.xml (location = '')"
Option no-compression is implied because wthttp was built without
zlib support.
[2016-Oct-31 08:21:09.372845] 4236 - [info] "WServer/wthttp:
initializing built-in wthttpd"
[2016-Oct-31 08:21:09.372845] 4236 - [info] "wthttp: started
server: http://0.0.0.0:80"
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85

Note, between the last two lines -- that is, before the line:

127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85

I killed the first server. I then browsed to the "nonexistant.html" url,
and the second server correctly responds with a 404 (because that
html page doesn't exist).


My second questions is about the WServer documentation and
error handling.

The documentation for WServer::start():

WTCONNECTOR_API bool Wt::WServer::start()

Starts the server in the background.

Returns whether the server could be successfully started.

Exceptions
Exception: indicates a problem starting the server.

This seems to be saying that when WServer::start() encounters
an error (regardless of whether my above example counts as
an error), the error condition is reported by returning false and
by throwing an exception. Of course, you can't actually do
both.

Are there two different classes of WServer::start() errors (maybe
for historical reasons), some of which are reported with a false
return value, and others that are reported with a thrown exception?

Anyway, what are the recommended best practices for handling
WServer::start() error conditions?


Thanks.


K. Frank
Aarón Bueno Villares
2016-10-31 13:36:04 UTC
Permalink
In my case (Ubuntu Server 14.04), when launching a second server instance
(from terminal of course) it throws me an error:

[2016-Oct-31 14:31:17.746221] 8337 - [info] "WServer/wthttp:
initializing built-in wthttpd"
[2016-Oct-31 14:31:17.747020] 8337 - [error] "wthttp: Error occurred
when binding to ::1:11000
bind: Address already in use"
Error (asio): bind: Address already in use

So, I conclude that it's the boost::asio library who throws an exception
with that message. `Wt` just displays it and the server launching is
stopped.

If your server runs and waits the port is free, or it's able to bind more
than one process to a same port, but in any case it's not halted, it must
be an OS-specific behaviour (otherwise, `boost::asio` should throw an
exception).
Post by K. Frank
Hello List!
(This is wt-3.3.3 compiled with mingw-w64 on windows 7.)
First, I see no errors when trying to start a wthttpd server on an
already bound port. What behavior should I expect?
Details: I've built a "minimal" wthttpd server -- it just servers
html files, so no WApplication. I run two copies of it at the
same time, both launched with "--http-port=80". The first
copy works, services http connections, and serves the html
pages. The second copy reports no errors, and doesn't receive
any http requests -- presumably because all of the port-80 traffic
goes to the first copy.
My understanding is that the first copy binds to port 80, and
everything works. I would expect that the second copy fails
to bind to port 80, which would seem to be to be an error
condition. But the second copy reports no errors.
int main (int argc, char *argv[]) {
try {
WServer server;
server.setServerConfiguration (argc, argv);
if (server.start()) WServer::waitForShutdown();
else cout << "error on server.start()" << endl;
}
catch (const WException& e) {
cout << "WException caught, e.whatA() = " << e.what() << endl;
}
return 0;
}
minimal_wt3 --http-address=0.0.0.0 --http-port=80
--deploy-path=/dummy --docroot=.
A little more detail: If I kill the first copy of the wthttpd server (and
just leave the second running, without restarting it or anything), the
second copy now responds to incoming connections, serves the
html pages, etc. Is this expected?
Option no-compression is implied because wthttp was built without
zlib support.
[2016-Oct-31 08:21:09.352845] 4236 - [info] "config: reading Wt
config file: c:/witty/wt_config.xml (location = '')"
Option no-compression is implied because wthttp was built without
zlib support.
initializing built-in wthttpd"
[2016-Oct-31 08:21:09.372845] 4236 - [info] "wthttp: started
server: http://0.0.0.0:80"
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85
I killed the first server. I then browsed to the "nonexistant.html" url,
and the second server correctly responds with a 404 (because that
html page doesn't exist).
My second questions is about the WServer documentation and
error handling.
WTCONNECTOR_API bool Wt::WServer::start()
Starts the server in the background.
Returns whether the server could be successfully started.
Exceptions
Exception: indicates a problem starting the server.
This seems to be saying that when WServer::start() encounters
an error (regardless of whether my above example counts as
an error), the error condition is reported by returning false and
by throwing an exception. Of course, you can't actually do
both.
Are there two different classes of WServer::start() errors (maybe
for historical reasons), some of which are reported with a false
return value, and others that are reported with a thrown exception?
Anyway, what are the recommended best practices for handling
WServer::start() error conditions?
Thanks.
K. Frank
------------------------------------------------------------
------------------
The Command Line: Reinvented for Modern Developers
Did the resurgence of CLI tooling catch you by surprise?
Reconnect with the command line and become more productive.
Learn the new .NET and ASP.NET CLI. Get your free copy!
http://sdm.link/telerik
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
K. Frank
2016-10-31 15:36:52 UTC
Permalink
Hi Aarón!

Thank you for your answer.

On Mon, Oct 31, 2016 at 9:36 AM, Aarón Bueno Villares
Post by Aarón Bueno Villares
In my case (Ubuntu Server 14.04), when launching a second server instance
Do you know what version of Wt you are using? (As a reminder, I am
using a copy of 3.3.3 that I built a couple of years ago.)
Post by Aarón Bueno Villares
initializing built-in wthttpd"
[2016-Oct-31 14:31:17.747020] 8337 - [error] "wthttp: Error occurred
when binding to ::1:11000
bind: Address already in use"
Error (asio): bind: Address already in use
First, am I right that the error appears in the console log (without
you writing any explicit code)?

Is the error otherwise reported? Are you calling WRun or are you
working with WServer directly? If you're working with WServer, are
you calling WServer::start(), and, if so, is it returning false?

Is any kind of c++ exception being thrown, in particular, a
WException or a WServer::Exception?
Post by Aarón Bueno Villares
So, I conclude that it's the boost::asio library who throws an exception
with that message. `Wt` just displays it and the server launching is
stopped.
Oddly enough, it's not obvious that my Wt application is using boost::asio.
(Although maybe it is.)

In my setup, I link statically to about half a dozen boost libraries (boost
1.57, by the way), for example, -lboost_program_options-mgw49-1_57
and -lboost_thread-mgw49-mt-s-1_57. I don't see anything that looks
like it would be asio. (Because io, in general, and sockets, in particular,
are os-dependent, I wouldn't expect boost::asio to be a header-only
library.) I do link to something called -lboost_system-mgw49-1_57.
Maybe boost::asio is hiding in there.
Post by Aarón Bueno Villares
If your server runs and waits the port is free, or it's able to bind more
than one process to a same port, but in any case it's not halted, it must be
an OS-specific behaviour (otherwise, `boost::asio` should throw an
exception).
I've done only a little hands-on winsock programming, and it's certainly
not fresh in my mind. But I would have expected (winsock's version of)
bind to fail with some sort of "port in use" error. So what you see on
linux is what I would have expected.

Any further thoughts would be appreciated. And it would be great if
a windows / winsock expert could chime in on what behavior would
normally be expected on windows.

(By the way, I do use winsock, linking with -lws2_32 and -lwsock32.)


I appreciate your help.


K. Frank
Post by Aarón Bueno Villares
Post by K. Frank
Hello List!
(This is wt-3.3.3 compiled with mingw-w64 on windows 7.)
First, I see no errors when trying to start a wthttpd server on an
already bound port. What behavior should I expect?
Details: I've built a "minimal" wthttpd server -- it just servers
html files, so no WApplication. I run two copies of it at the
same time, both launched with "--http-port=80". The first
copy works, services http connections, and serves the html
pages. The second copy reports no errors, and doesn't receive
any http requests -- presumably because all of the port-80 traffic
goes to the first copy.
My understanding is that the first copy binds to port 80, and
everything works. I would expect that the second copy fails
to bind to port 80, which would seem to be to be an error
condition. But the second copy reports no errors.
int main (int argc, char *argv[]) {
try {
WServer server;
server.setServerConfiguration (argc, argv);
if (server.start()) WServer::waitForShutdown();
else cout << "error on server.start()" << endl;
}
catch (const WException& e) {
cout << "WException caught, e.whatA() = " << e.what() << endl;
}
return 0;
}
minimal_wt3 --http-address=0.0.0.0 --http-port=80
--deploy-path=/dummy --docroot=.
A little more detail: If I kill the first copy of the wthttpd server (and
just leave the second running, without restarting it or anything), the
second copy now responds to incoming connections, serves the
html pages, etc. Is this expected?
Option no-compression is implied because wthttp was built without
zlib support.
[2016-Oct-31 08:21:09.352845] 4236 - [info] "config: reading Wt
config file: c:/witty/wt_config.xml (location = '')"
Option no-compression is implied because wthttp was built without
zlib support.
initializing built-in wthttpd"
[2016-Oct-31 08:21:09.372845] 4236 - [info] "wthttp: started
server: http://0.0.0.0:80"
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85
I killed the first server. I then browsed to the "nonexistant.html" url,
and the second server correctly responds with a 404 (because that
html page doesn't exist).
...
Thanks.
K. Frank
Aarón Bueno Villares
2016-10-31 15:56:35 UTC
Permalink
I'm not sure, but I will say that the WServer implementation uses
`boost::asio` no matter in which platform you are. The linking takes place
in the wthttpd connector, which is already linked in the .so or in the .dll
in your case or whatever the file extension is for statically linked
libraries in Windows (by the way, I use the wthttpd connector, neither
isapi nor fcgi).

So, you have no way of knowing whether `boost::asio` is being linked or not
looking at your manually added libraries, because the libraries needed by
your connector are already linked in the connector object file itself (I'm
not an expert, though, but I would say yes to that).

My Wt version is 3.3.4 and no, I haven't written any explicit code.To try
to convince you further, the string I receive, "Address already in use",
doesn't appear in the source code of Wt (WServer interface or connector
--which implements some functions of WServer, so, linking against different
connectors, get different implementation of those WServer's delegated
functions).

However, the string "Error occurred when binding" does appear in
http/Server.C, so, the exception is being captured by Wt in the wthttp
connector source code, and after printing that line, it prints the
exception message ("Address already in use") carried on the `boost`
exception thrown by the `tcp_endpoint` object when trying to connect to the
configured port.
Hi Aarón!
Thank you for your answer.
On Mon, Oct 31, 2016 at 9:36 AM, Aarón Bueno Villares
Post by Aarón Bueno Villares
In my case (Ubuntu Server 14.04), when launching a second server instance
Do you know what version of Wt you are using? (As a reminder, I am
using a copy of 3.3.3 that I built a couple of years ago.)
Post by Aarón Bueno Villares
initializing built-in wthttpd"
[2016-Oct-31 14:31:17.747020] 8337 - [error] "wthttp: Error occurred
when binding to ::1:11000
bind: Address already in use"
Error (asio): bind: Address already in use
First, am I right that the error appears in the console log (without
you writing any explicit code)?
Is the error otherwise reported? Are you calling WRun or are you
working with WServer directly? If you're working with WServer, are
you calling WServer::start(), and, if so, is it returning false?
Is any kind of c++ exception being thrown, in particular, a
WException or a WServer::Exception?
Post by Aarón Bueno Villares
So, I conclude that it's the boost::asio library who throws an exception
with that message. `Wt` just displays it and the server launching is
stopped.
Oddly enough, it's not obvious that my Wt application is using boost::asio.
(Although maybe it is.)
In my setup, I link statically to about half a dozen boost libraries (boost
1.57, by the way), for example, -lboost_program_options-mgw49-1_57
and -lboost_thread-mgw49-mt-s-1_57. I don't see anything that looks
like it would be asio. (Because io, in general, and sockets, in particular,
are os-dependent, I wouldn't expect boost::asio to be a header-only
library.) I do link to something called -lboost_system-mgw49-1_57.
Maybe boost::asio is hiding in there.
Post by Aarón Bueno Villares
If your server runs and waits the port is free, or it's able to bind more
than one process to a same port, but in any case it's not halted, it
must be
Post by Aarón Bueno Villares
an OS-specific behaviour (otherwise, `boost::asio` should throw an
exception).
I've done only a little hands-on winsock programming, and it's certainly
not fresh in my mind. But I would have expected (winsock's version of)
bind to fail with some sort of "port in use" error. So what you see on
linux is what I would have expected.
Any further thoughts would be appreciated. And it would be great if
a windows / winsock expert could chime in on what behavior would
normally be expected on windows.
(By the way, I do use winsock, linking with -lws2_32 and -lwsock32.)
I appreciate your help.
K. Frank
Post by Aarón Bueno Villares
Post by K. Frank
Hello List!
(This is wt-3.3.3 compiled with mingw-w64 on windows 7.)
First, I see no errors when trying to start a wthttpd server on an
already bound port. What behavior should I expect?
Details: I've built a "minimal" wthttpd server -- it just servers
html files, so no WApplication. I run two copies of it at the
same time, both launched with "--http-port=80". The first
copy works, services http connections, and serves the html
pages. The second copy reports no errors, and doesn't receive
any http requests -- presumably because all of the port-80 traffic
goes to the first copy.
My understanding is that the first copy binds to port 80, and
everything works. I would expect that the second copy fails
to bind to port 80, which would seem to be to be an error
condition. But the second copy reports no errors.
int main (int argc, char *argv[]) {
try {
WServer server;
server.setServerConfiguration (argc, argv);
if (server.start()) WServer::waitForShutdown();
else cout << "error on server.start()" << endl;
}
catch (const WException& e) {
cout << "WException caught, e.whatA() = " << e.what() << endl;
}
return 0;
}
minimal_wt3 --http-address=0.0.0.0 --http-port=80
--deploy-path=/dummy --docroot=.
A little more detail: If I kill the first copy of the wthttpd server
(and
Post by Aarón Bueno Villares
Post by K. Frank
just leave the second running, without restarting it or anything), the
second copy now responds to incoming connections, serves the
html pages, etc. Is this expected?
Option no-compression is implied because wthttp was built without
zlib support.
[2016-Oct-31 08:21:09.352845] 4236 - [info] "config: reading Wt
config file: c:/witty/wt_config.xml (location = '')"
Option no-compression is implied because wthttp was built without
zlib support.
initializing built-in wthttpd"
[2016-Oct-31 08:21:09.372845] 4236 - [info] "wthttp: started
server: http://0.0.0.0:80"
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85
127.0.0.1 - - [2016-Oct-31 08:22:34.961484] "GET /nonexistant.html
HTTP/1.1" 404 85
I killed the first server. I then browsed to the "nonexistant.html"
url,
Post by Aarón Bueno Villares
Post by K. Frank
and the second server correctly responds with a 404 (because that
html page doesn't exist).
...
Thanks.
K. Frank
------------------------------------------------------------
------------------
The Command Line: Reinvented for Modern Developers
Did the resurgence of CLI tooling catch you by surprise?
Reconnect with the command line and become more productive.
Learn the new .NET and ASP.NET CLI. Get your free copy!
http://sdm.link/telerik
_______________________________________________
witty-interest mailing list
https://lists.sourceforge.net/lists/listinfo/witty-interest
K. Frank
2016-10-31 23:54:58 UTC
Permalink
Hello Aarón!

On Mon, Oct 31, 2016 at 11:56 AM, Aarón Bueno Villares
Post by Aarón Bueno Villares
I'm not sure, but I will say that the WServer implementation uses
`boost::asio` no matter in which platform you are. The linking takes place
in the wthttpd connector, which is already linked in the .so or in the .dll
in your case or whatever the file extension is for statically linked
libraries in Windows (by the way, I use the wthttpd connector, neither isapi
nor fcgi).
So, you have no way of knowing whether `boost::asio` is being linked or not
looking at your manually added libraries, because the libraries needed by
your connector are already linked in the connector object file itself (I'm
not an expert, though, but I would say yes to that).
Yes, that makes sense. I do link to -lwthttp (as well as -lwt). This
resolves to libwthttp.a, a mingw-w64 / windows static library that
presumably has boost::asio linked into it.
Post by Aarón Bueno Villares
My Wt version is 3.3.4 and no, I haven't written any explicit code.To try to
convince you further, the string I receive, "Address already in use",
doesn't appear in the source code of Wt (WServer interface or connector
--which implements some functions of WServer, so, linking against different
connectors, get different implementation of those WServer's delegated
functions).
However, the string "Error occurred when binding" does appear in
http/Server.C, so, the exception is being captured by Wt in the wthttp
connector source code, and after printing that line, it prints the exception
message ("Address already in use") carried on the `boost` exception thrown
by the `tcp_endpoint` object when trying to connect to the configured port.
Thank you. Your linux experience makes perfect sense to me. The
mystery is why my windows version doesn't work the way I would
expect conventional socket code to work, even on windows.

It doesn't seem likely that something like this would have changed
between 3.3.3 and 3.3.4. It's probably just some windows weirdness.

This isn't really an issue for me -- I was just surprised when I noticed
this behavior.


Best regards.


K. Frank
Post by Aarón Bueno Villares
Post by K. Frank
Hi Aarón!
Thank you for your answer.
On Mon, Oct 31, 2016 at 9:36 AM, Aarón Bueno Villares
Post by Aarón Bueno Villares
In my case (Ubuntu Server 14.04), when launching a second server instance
Do you know what version of Wt you are using? (As a reminder, I am
using a copy of 3.3.3 that I built a couple of years ago.)
...
Loading...