[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#4606) Big LDAP Search responses causes IO error in libldap on Windows XP



Howard Chu wrote:

> Hm, on my Visual Studio6 errno.h does a
>    #define errno *_errno()
> and of course _errno() is an imported function. This problem 
> "shouldn't happen."

Well, it does for me using Visual Studio 8. I've added printf statements 
inside liblber (after errno was set) and in libldap after the liblber 
function has returned and errno was set to 0.
Anyway, WSASetLastError() is a clean "Windows" way of achieving the same 
result.

> In your patch, directly including <errno.h> should not be needed, 
> since <ac/errno.h> will include it already. If <ac/errno.h> isn't 
> bringing in <errno.h> for you then it appears you have a configure 
> problem.

That is fine.

This reminds me that there is another problem with configure. The 
following code in <ac/errno.h> doesn't compile with Visual Studio 8:

#elif DECL_SYS_ERRLIST
    /* have sys_errlist but need declaration */
    LDAP_LIBC_V(int)      sys_nerr;
    LDAP_LIBC_V(char)    *sys_errlist[];
#endif

sys_errlist and sys_nerr are defined in <stdlib.h>, and not in <errno.h>

> alexey.melnikov@isode.com wrote:
>
>> Full_Name: Alexey Melnikov
>> Version: 2.2.27
>> OS: Windows XP Professional
>> URL: ftp://ftp.openldap.org/incoming/
>> Submission from: (NULL) (62.3.217.250)
>>
>>
>> Problem symptoms: LDAP Search that returns about 20Kb of data is 
>> failing in the
>> middle of decoding with IO error.
>>
>> Problem description: liblber code is using recv() to read data from 
>> socket on
>> Windows. If there is some data in the TCP buffer already, the 
>> function would
>> complete immediately (without blocking), returning number of bytes
>> in the buffer. This can lead to a situation when the caller requests,
>> say 100 bytes, but only gets 32. If the caller needs more data
>> it would call the recv function again to get more data.
>> liblber ber_get_next() was setting errno to EAGAIN or EWOULDBLOCK
>> (depending on which one is defined on the platform) to signal to
>> the caller that it needs to call ber_get_next again to get more data.
>> For some bizarre reason when errno is set in liblber, it is not
>> set when execution returns to libldap. I suspect both DLLs have
>> private copies of the same errno value.
>> The end result of errno not being set is that libldap thinks that
>> there was some socket error and fails the current operation.
>>
>> The fix is to use WSASetLastError/WSAGetLastError on Windows.
>> They operate on per thread value and work correctly accross DLL
>> boundaries.
>>
>> libldap/liblber were built using /MD flag (to link with 
>> "Multithreaded DLL" C
>> library), using Visual Studio 8 (2005).
>>
>> I've compares changes to libldap/liblber code between 2.2.27 and 
>> trunk of 2.3.X
>> branch and I think the problem is still there.
>