This mail is addressed to Dr Stephen N. Henson in connection with his previous
post.
> I have never come across a report of a deadlock in that situation and several
> applications have reported using WSAEventSelect() in the past. There are
> several possible reasons...
>
There is very,very little chance the application to deadlock. 'send' command
fails very rare. I have made a test - I've sent about 100 Mb at one time using
nonblocking socket and windows consumed whole buffer at one time and
immediately returned without any error and with 100 Mb send (the data wasn't
send of course) - it means that it has large enough buffer to consume big
amount of data. I'm using windows xp, i don't know how it works on older
systems (NT,98,me) maybe there is bigger probability to 'send' failure. That's
not all, i'm coding simple jabber client (i hope you know what is jabber). I've
downloaded source code for one of the freeware clients recommended by main
jabber.org site (by the way, this client is recommended at first place as
windows client). I've looked at source and it seems that it uses openSSL
improperly - in winsock fashion (which is good for unencrypted connection - it
depends on jabber server),using 2 thread one for reading and one for writing,
without any openSSL command serialization. (This is my opinion, maybe i've
missed something but i don't think so, it's written in delphi and it uses indy
components) But even using this rather improper for openSSL style, it seems
that it doesn't cause much trouble. Probability of reading and writing exactly
at the same time for communicator application is rather small, additionally
scheduler must switch the threads in special moment of their work to cause race
condition. So, deadlocks for most application are very rare and it is rather
matter of correctness then real problem in real applications causes me to find
proper way of implementing OpenSSL app.
> 1. The application works because of the feature mentioned in KB186245.
>
I'm using XP
> 2. The send() function never returns any of the other BIO_sock_non_fatal_error
> codes so this is not an issue in practice. The documentation seems to suggest
> this but that's no guarantee.
>
Well, that's the problem. I have no certainty that this is true and it will be
true for further openSSL implementations, so i have to develop code to deal
with it.
> Call select() with a zero second timeout. If it indicates socket is
> writable retry the opertion, if not call WSAEventSelect().
Theoretically this should be true since if openSSL returns error WANT_WRITE and
it is not caused by WSAEWOULBLOCK (FD_WRITE event won't be send) it means that
operation should just be immediatelly repeated and 'select' can be used to
check this situation. But very theoretically i some case WANT_WRITE will not be
send since windows can't check when writing will be possible. Windows signals
this returning error other then WSAEWOULDBLOCK and some other checking method
should be used, for example: repeated socket polling ('select' with timeout >
0).(I hope you know what i mean) I know this is very abstract case, but it
should reminded that OS API is something what is developed by many years for
different OS versions, sometimes API is imported for compatibility from
diffrent OSes, etc. So using only good sense is not reliable way to success.
(for example why 'select' doesn't support socket and pipes at the same time?
Won't it be better then implementing WSAXXX framework?). The only reliable way
is to implement excactly with OS API specyfication.
>
> Call WSAGetLastError() to confirm the error code.
>
Yes,i have seen this method in some thread of this mailing list, but i think
that it's not reliable method. I have no certainty that OpenSSL doesn't reset
error code or some other windows command is not invoked after 'send' failure.
>
> One is to write a custom socket BIO. In this case it would be very simple
> because it would copy all the existing methods *except* the write behaviour
> which would set the retry flag only if the error is WSAEWOULDBLOCK.
>
Unfortunately i'm using Delphi and openSSL is written in c, so it's not such
easy for me.
> The second alternative is BIO pairs this give an application total flexibility
> on all socket I/O but is more complex to handle.
>
Yes, much more.
I've developed some method, but i has limited usage, it can be used for some
special kind of applications using one socket for reading and writing. (but
this is exactly my case) Application must wait for 3 events: reading event,user
event(used to tell that user want write) and write event(used only if
WANT_WRITE occured). This trick is tightly connected with application
logic.When app starts it waits for 2 events: FD_READ event and user event, it
does it using 'WaitForMultipleObjects' command. It uses this construction all
time till WANT_WRITE error will occur, then it can switch to loop which uses
'select' statement as blocking function - the trick is very simple, when app
can't write it doesn't have to wait for user event,
so 'select' statement can be used. When 'select' returns ability to write app
can again switch to 'WaitForMultipleObjects' and so on. Do you ever came across
this implementation? What do you think abou it? Have i missed something?
I have one question to you, yet. If SSL_write blocks with WANT_WRITE error,
theoretically i can still use SSL_read ? (I think i can). But what to do when
SSL_read will return WANT_WRITE error? Which command i should repeat first?
SSL_read, SSL_write or it doesn't metter?
Lucas
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [EMAIL PROTECTED]