windows overlapped files

235 views
Skip to first unread message

Tarmigan

unread,
Apr 20, 2011, 3:36:14 PM4/20/11
to golang-dev, Russ Cox, alex.b...@gmail.com, Hector Chu
Hi,

I have been working on a package to communicate with serial ports. On
unixy systems (though only tested on OSX) I use cgo and termios.h and
it's pretty straightforward and it works nicely for me.

I am much less familiar with Windows, but I have been using a
combination of go's os.Open and cgo to access SetCommState and
SetCommTimeouts. This worked OK, but I wanted a Read function that
would block until at least one byte was received. To do this, I setup
the Timeouts to return immediately and then wrote my own Read()
function that called WaitCommEvent through cgo (which can block until
a character is received on the serial port) before calling the generic
(*os.File)Read(). This worked well for one project I was working on.

My current trouble (as far as I can tell) is that go's Write() in one
goroutine will block waiting for the cgo WaitCommEvent (called from my
Read()) because Windows does not allow concurrent ReadFile/WriteFile/
WaitCommEvent on filehandles that are not overlapped. This works OK
if you are constantly receiving data (as I was in one project) but
falls down if you only receive data in response to data you send.
From what I have read, I think the correct solution to this is to open
the file with CreateFile with the FILE_FLAG_OVERLAPPED flag set and
then pass a real Overlapped data structure to ReadFile/WriteFile/
WaitCommEvent and then call GetOverlappedResult or WaitForSingleObject
to wait for the result of those functions.

Option 1 would be to copy os.Open(), (*os.File)Read(), and
(*os.File)Write() and add the Overlapped data structures and
GetOverlappedResult extra bits in my own copy. This seems error-prone
and like a lot of duplication.

Option 2 would be to modify the os package to open all files with
FILE_FLAG_OVERLAPPED. Not sure what other implications that change
might have.

Option 3 is a hack to set the the serial port read timeout to 1ms and
just Read() in a while loop which would let the Write() go through
eventually.

Option 4 is ???

Thoughts?

Reading through the sources, I'm not sure how syscall.Pread works on
windows with a file that was opened with os.Open because seems to me
like it would need to be opened with FILE_FLAG_OVERLAPPED for the
Overlapped data structure used in syscall.Pread to be effective. But
I have not tested.

I've been looking through the windows syscall files and find the
approach very interesting. Eventually, I would like to use
syscall.LoadLibrary instead of cgo for WaitCommEvent/SetCommState/
SetCommTimeouts. The advantage to me of using syscall instead of cgo
is that I can cross compile for windows without having to boot into
windows. It's still a bit scary to lose the type checking though.

Thanks,
Tarmigan

brainman

unread,
Apr 21, 2011, 12:23:50 AM4/21/11
to golan...@googlegroups.com, Russ Cox, alex.b...@gmail.com, Hector Chu
>>>
..., I think the correct solution to this is to open
the file with CreateFile with the FILE_FLAG_OVERLAPPED flag set and
then pass a real Overlapped data structure to ReadFile/WriteFile/
WaitCommEvent and then call GetOverlappedResult or WaitForSingleObject
to wait for the result of those functions. ...
<<<

Sounds like a plan. I use to do just that long time ago when talking to a serial port. You would have to employ Windows event in Overlapped structure, then you could wait for data to arrive.

>>>
Option 4 is ???
<<<

You could start from scratch, like net package. It is not trivial, but if you know what you're doing, it shouldn't be too much code.


>>>
Reading through the sources, I'm not sure how syscall.Pread works on
windows with a file that was opened with os.Open because seems to me
like it would need to be opened with FILE_FLAG_OVERLAPPED for the
Overlapped data structure used in syscall.Pread to be effective.
<<<

Not true. We use Overlapped to specify file offset. There is no really "overlapped" io there. If you look at the manual, it is there.


>>>
I've been looking through the windows syscall files and find the
approach very interesting. Eventually, I would like to use
syscall.LoadLibrary instead of cgo for WaitCommEvent/SetCommState/
SetCommTimeouts. The advantage to me of using syscall instead of cgo
is that I can cross compile for windows without having to boot into
windows. It's still a bit scary to lose the type checking though.
<<<

It's quite easy to generate any system Windows calls. Just look at src/pkg/exp/wingui (see how zwinapi.go is generated). You could easily build all your required function calls. I don't understand your last statement about "type checking".

Alex

Tarmigan

unread,
Apr 29, 2011, 7:54:07 PM4/29/11
to golang-dev, brainman, Russ Cox, Hector Chu
Sorry, looks like you replied, but I didn't see it because I'm not
subscribed. My bad.

Looking at it now...

Thanks,
Tarmigan
Reply all
Reply to author
Forward
0 new messages