Re: courier-imap unable to open INBOX

From: Frank Leonhardt <freebsd-doc_at_fjl.co.uk>
Date: Tue, 25 Feb 2025 18:38:43 UTC
On 2025-02-25 17:01, Frank Leonhardt wrote:
> On 2025-02-16 13:52, Benjamin Lutz wrote:
>> In order to better understand it, I built courier-imap with debugging 
>> flags and added some debugging code around the line above:
>> 
>>     errno=-999;
>>     int stat_retval=stat( info->tmpname, &stat_buf);
>>     fprintf(stderr, "stat=%p, stat(%p, %p), stat_retval=%d, errno=%d,
>>         strerror(errno)=%s\n", stat, info->tmpname, &stat_buf,
>>         stat_retval, errno, strerror(errno));
>>     if (stat_retval == 0)
>> 
>> When SELECTing the INBOX now, I get:
>> 
>>     stat=0x823bc4f70, stat(0x2f67a4269000, 0x820949b40), 
>> stat_retval=-1,
>>         errno=-999, strerror(errno)=Unknown error: -999
>>     a NO Unable to open this mailbox.
>> 
>> So errno isn't changed by stat(2) (confirmed with other values than 
>> -999). This has me rather perplexed. How can a stat(2) call not set 
>> errno? As far as I can tell using GDB, that stat() call really is a 
>> call into libc, not some other function that might shadow stat(2).
>> 
> 
> Perplexing indeed. I've just verified libc for FreeBSD 14.2 does indeed 
> set errno (which isn't exactly an int, BTW). It would correctly leave 
> the error code alone if there was no error, but your return value of -1 
> means there is an error.
> 
> FWIW, the next thing I'd explore is whether the "errno" in the code is 
> the same as the system errno, which is defined in sys/errno.h. As I 
> said, it's not an int so if it's declared as "extern int errno" you may 
> see strange things happen.

I could have explained the context better - errno in a multi-threaded 
environment cannot be a simple int for obvious reasons and I suspect an 
imap server may be multi-threaded. You can see this for yourself in the 
header I mentioned - basically it's a macro that calls a function to get 
the address of the appropriate errno for the thread, unless it's the 
initial thread. This still uses the global variable. Hence I wondered 
about your attempt to isolate the call to a simple use case. I could, of 
course, be barking up the wrong tree.

Regards, Frank.