[Box Backup-dev] 0.11rc1 win32 code review

Chris Wilson boxbackup-dev@fluffy.co.uk
Sun, 27 Jan 2008 23:19:48 +0000 (GMT)


Hi Charles,

On Sun, 27 Jan 2008, Charles Lecklider wrote:

> I had a few spare minutes today so I thought I'd take a quick look 
> through the code for rc1. I've not looked through everything, but what I 
> did seems to have far fewer bits of Win32-specific stuff scattered 
> through it, and that can only be a good thing.
> 
> If there are any Win32 parts I've not listed that you think are worth a 
> look let me know and I'll try to find some more time later this week.

Many, many thanks for taking the time to do this! Most of the things you 
pointed out look to be relatively easy to fix. I'll address them over the 
next few days.

But I have a big problem with the overlapped I/O stuff. Basically it makes 
the whole code for WinNamedPipeStream very difficult to read and 
understand the correctness of. I get a lot of errors from this code during 
the unit tests on Windows, and it sometimes hangs on XP (perhaps even on 
2K).

I'd really like to remove overlapped I/O completely. But I have a bit of a 
problem with that too, which is why I introduced it in the first place.

On Windows, we use a thread in BackupDaemon to manage the named pipe. 
Because it appears to be unsafe (causes deadlocks) to access the pipe in 
multiple threads (e.g. to Write() status messages from the main thread 
while the listener thread is blocked on Read()), I have to pass messages 
from the main thread to the listener thread and signal an Event when a new 
message is available for the listener to write to the named pipe.

Now the problem comes when multiple messages are received by the named 
pipe (from the control client). I haven't found a way to tell if there are 
still more messages (or bytes) queued on the pipe. If I just 
WaitForMultipleObjects(main-thread-event, named-pipe) then I don't know 
how many messages to read from the named pipe. If I just read one, then I 
could miss an important message, never read it and deadlock with the 
control client. If I read more than one, I'll end up blocking on Read() 
and never read any more messages from the main thread, so I could also 
deadlock if the control client is waiting for a message from the main 
thread (such as sync finished).

I really wanted to do a non-blocking read on the named pipe, to discover 
whether there are more messages waiting without blocking (and probably 
deadlocking) but I can't see how. Do you have any ideas about this?

Second question (easier I hope): I noticed that Win32 has a Timer API 
(CreateTimerQueueTimer) and I tried to use this to replace the horrible 
RunTimer thread, but the events seem to be delivered very late or not at 
all. I can post sample code if it helps (I don't want to commit it because 
it's badly broken), but do you have any recommendations about it or ideas 
why it might not be working properly? I think you recommended using 
something different in the past, was it Waitable Timer objects? Do they 
work better? 

Cheers, Chris.
-- 
_____ __     _
\  __/ / ,__(_)_  | Chris Wilson <0000 at qwirx.com> - Cambs UK |
/ (_/ ,\/ _/ /_ \ | Security/C/C++/Java/Ruby/Perl/SQL Developer |
\ _/_/_/_//_/___/ | We are GNU : free your mind & your software |