[freetds] tds_socketpair on windows
freddy77 at gmail.com
Mon Apr 2 14:05:39 EDT 2012
Il 02 aprile 2012 01:54, James K. Lowden <jklowden at freetds.org> ha scritto:
> On Sun, 1 Apr 2012 22:57:04 +0100
> Frediano Ziglio <freddy77 at gmail.com> wrote:
>> I don't understand why
>> > we need a pair of sockets. To support MARS?
>> One reason is MARS, another is to support all cancellation cases in a
>> signal and thread safe way (I don't remember the exact combination
>> that causes problems but I start writing this code before MARS).
> Then I doubt it's necessary, strictly speaking. Stevens shows tcp/ip
> can (and should) be managed with one thread of control. I would be
> happy to help you meet your goals using just one socket, if you can
> explain what led you to creating the pair.
> Signals and threads don't mix, as you know.
>> > WaitForSingleObject() requires threads. event_fd is not portable
>> > and not POSIX.
>> Windows always support threads.
> Yes. Threads might not be the worst thing Windows brought to
> programming, but they're close.
> The point isn't whether or not threads are supported. The point is:
> Do threads make the code easier to understand and reason about?
> The answer is almost always No.
> As I'm sure you agree, the more we can use portable constructs and a
> single thread of source code, the better off we are.
>> And perhaps the gain is not as good as other optimizations.
> The first rule of optimization is: measure. FreeTDS is pretty
> efficient as it is. It would be easy to make it more complex without
> making it any faster.
> The Big Optimization could come from my automaton. Early
> measurements indicate a state machine could manage the TDS layer with
> about 10% of the code, no copies, and no mallocs (except for packets).
> I've taken some time to read about binary parsers e.g. binpac
> It's not clear to me that a parser-generator buys us anything over my
> do-it-yourself approach. But I'd like to be convinced before going
All came from cancel stuff. Mainly libraries specification not use
neither thread neither signals... except the cancel which, believe or
not have both!
There is a "cancel" test (I think in ODBC) that check both and failed
1 time out of 4 :(
Now it always works.
The reason I came to socketpair is quite complicated.
>From dblib/ctlib specification cancel can be called from a signal handler.
>From MS specifications (SQLCancel) cancel can be called from another thread.
So now what should do tds_cancel? How to signal the thread or caller
correctly and in a safe way?
We are a library so we shouldn't change global state (like calling
signal/sigaction or setsigmask). Also if caller use thread (like
Apache and PHP for instance) we must be thread safe while if somebody
use just a single thread program and handle user input like ctrl-c
sending a cancel we must be signal safe.
If the other "thing" is reading to server it can just send a cancel
and expect server reply and send a proper cancel reply.
On write is more complicated cause it cannot write and so it has to
signal the other to send a cancel when it can. But how to signal?
Setting a variable at first sight seemed ok but it cause a race
condition that is hard to manage.
You could try to stop signal, do the checks and then restart signaling
but the only functions that can do this in a safe way are
pthread_setsigmask and pselect which are not that portable.
How cancel should detect that something is working on the socket and
not break data?
Just to complicate things to support tls you cannot write to socket
without checking for read cause on long write to server could require
crypt key change so we need always to test for read. And SSL_read
could also write to socket (cause client decide to change key).
More information about the FreeTDS