> From: Lutz Jaenicke [mailto:[EMAIL PROTECTED]]
> Sent: Monday, February 05, 2001 7:41 AM

> Continuing discussion of the problem:
> 
> (The system is identified as Unixware-7.)
> 1. When disabling threads in the Configure phase of OpenSSL, the
connection
>    to the entropy daemon is opened fine.
> 2. When supporting threads (the default for unixware-7), the 'connect()'
>    system call comes back with EINTR. When calling connect() in a loop,
>    it then returns with EISCONN, because it already seems to be connected.
>    I have now patched rand_egd.c (0.9.6a-dev) to perform the following
loop,
>    which is working out fine for unixware-7 with threading (please ignore
>    the fprintf-debugging at the end :-):

Sounds like the threading engine in UW is using timer interrupts.  This may
cause other "slow" system calls to EINTR-out, too, so OpenSSL may need EINTR
loops around socket reads and writes (if it doesn't already have them).

[snip what appears to be a solid EINTR loop patch to rand_egd.c's connect
call]

> Would it make sense to include this into the openssl source as a standard
> solution? Even more: are there better ideas avaible?

I don't see any problems with enclosing the connect in an EINTR-restart
loop; that's pretty standard with "slow" system calls in an environment
where they may be interrupted by unrelated events.  There will be behavior
change in some unusual circumstances, though, which might conceivably cause
some confusion.  For example, if someone had an OpenSSL app that caught
SIGINT but didn't do anything dramatic with it, and they were in the habit
of hitting ctrl-C while that app was trying to connect to the egd socket,
that ctrl-C would break out of the connect in the old code; in the new code,
rand_egd will retry the connect.  I think that's pretty minor.

Another suggestion: On some platforms (eg. Solaris 2.6 and Unixware 2.1.2; I
haven't tested more recent versions thoroughly), if you have a race between
the daemon creating the socket (actually, when it calls listen) and the
client opening it, you can get ECONNREFUSED in the client.  When that
happens, you have to close the client's socket and re-create it before you
can call connect again - the ECONNREFUSED "sticks" to the client's socket.
So you might want to put the socket call itself in the loop, along the lines
of

> +       do {
> +         ret=connect(fd, (struct sockaddr *)&addr, len)
            if (errno == ECONNREFUSED) {
               close(fd);
               fd = socket(...);
               if (fd < 0) return(-1);
               }
            else if (errno != EINTR)
               break;
> +       } while (ret < 0);

I moved the EINTR test into the loop to avoid having an overly complex
invariant after the while.  Adjust the logic to suit your taste, of course.
(Personally, I'd probably use a flag variable in production code, for
clarity.)

Michael Wojcik             [EMAIL PROTECTED]
MERANT
Department of English, Miami University
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [EMAIL PROTECTED]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to