More DispatchIO problems -- cleanup handler isn't called

I create a DispatchIO object (in Swift) from a socketpair, set the low/high water marks to 1, and then call read on it. Elsewhere (multi-threaded, of course), I get data from somewhere, and write to the other side of it. Then when my data is done, I call dio?.close()

The cleanup handler never gets called.

What am I missing? (ETA: Ok, I can get it to work by calling dio?.close(flags: .stop) so that may be what I was missing.)

(Also, I really wish it would get all the data available at once for the read, rather than 1 at a time.)

Answered by DTS Engineer in 814002022

Glad to hear you got the cleanup issue resolved.

Also, I really wish it would get the data available at once for the read, rather than 1 at a time.)

DispatchIO gives you control over how it groups the data that it reads. To start, there’s the length parameter on the read routine itself, but there’s also various options listed under Managing the File Descriptor in the docs.

When working with sockets the best way to ensure that the data arrives as a unit is to write the data as a unit. So, imagine you’re framing each message with a 32-bit length header. Don’t write the header and then write the message, but rather prepend the header to the message and write them together.

IMPORTANT While this can help, if you’re using a streaming socket then there’s no guarantee that it’ll preserve message boundaries.

One little know feature of Unix domain sockets is that they support datagram sockets, and thus do preserve boundaries. And they’re reliable, unlike say UDP.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Glad to hear you got the cleanup issue resolved.

Also, I really wish it would get the data available at once for the read, rather than 1 at a time.)

DispatchIO gives you control over how it groups the data that it reads. To start, there’s the length parameter on the read routine itself, but there’s also various options listed under Managing the File Descriptor in the docs.

When working with sockets the best way to ensure that the data arrives as a unit is to write the data as a unit. So, imagine you’re framing each message with a 32-bit length header. Don’t write the header and then write the message, but rather prepend the header to the message and write them together.

IMPORTANT While this can help, if you’re using a streaming socket then there’s no guarantee that it’ll preserve message boundaries.

One little know feature of Unix domain sockets is that they support datagram sockets, and thus do preserve boundaries. And they’re reliable, unlike say UDP.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I didn't really solve it -- it's a hacky work-around. When I call dio?.close()... it should close. It doesn't. And because it's busy doing one byte of I/O at a time, there was pending data; I had to change it to close it after a delay (0.5 seconds).

I don't know what amount the other side is sending. My read-length is 1024 (this is my go-to length when I'm reading from a network), my sample case is 18 bytes in my unit test, it's written all at once, but because of the water marks, the read handler is called 18 times. Well, 19 because of the delayed .close(flags: .stop).

If I set the water-marks to something other than 1, then it always waits until the length is available. Which doesn't work when the connection is interactive.

Thus:

Also, I really wish it would get the data available at once for the read, rather than 1 at a time.)

More DispatchIO problems -- cleanup handler isn't called
 
 
Q