Live data from Hacker News

Dyad: Minimal, portable async networking library for C

github.com

41–47 of 47 posts

Re: Dyad: Minimal, portable async networking library for C

#41
post #33
post #16

Earlier quoted context omitted.

I know what select/epoll and friends are for. What's wrong with tying up one thread per socket?

Probably nothing. {taking aside performance issues when you run into the thousands of parallel connections} I personally prefer the old-school async approach, because there you are forced to explicitly manage your connections' state, and the application/process-wide data access is inherently race-condition free. I'd use this as far as possible. If you let your OS schedule threads, obviously you have to be careful tha…

Using async to avoid race conditions due to multiple threads was great 15-20 years ago when single CPU machines ruled, but now you need multiple threads or processes for concurrency. Using multiple processes is usually not an option due to lack of any shared state (and if you're trying to share state across processes you should probably just use threads).

Re: Dyad: Minimal, portable async networking library for C

#42
post #16
post #15

Earlier quoted context omitted.

You need select or a select-like function to know which sockets are readable/writable without tying up one thread per socket

I know what select/epoll and friends are for. What's wrong with tying up one thread per socket?

In addition to the problems discussed in the other replies, it's (nearly?) impossible to correctly cancel an operation while blocked on a socket.

Re: Dyad: Minimal, portable async networking library for C

#43

Earlier quoted context omitted.

How are you supposed to do socket programming without select?

poll is fairly portable, but still has scaling problems. To get beyond scaling problems, you usually need something OS-specific, such as epoll (Linux), kqueue (BSDs of some kind), etc. One of the things I'd expect of a cross-platform networking library would be to use the best available abstraction, especially on major platforms such as linux, and perhaps fall back to select on odd platforms. Of course, your docs nee…

libev - http://software.schmorp.de/pkg/libev.html -is an existing library that provides async networking IO, over a number of backends including (I think) kqueue, epoll and in the worst case, select.

Re: Dyad: Minimal, portable async networking library for C

#44
post #42
post #16

Earlier quoted context omitted.

I know what select/epoll and friends are for. What's wrong with tying up one thread per socket?

In addition to the problems discussed in the other replies, it's (nearly?) impossible to correctly cancel an operation while blocked on a socket.

Have you tried:

* closing the socket (it would be from another, monitoring thread in this case)

* setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO)

* Would that be different than blocking on select with a an infinite timeout. How do you cancel that? Or are you relying on other sockets getting constant stream of data to wake you up?

* do something with an ALARM signal

Re: Dyad: Minimal, portable async networking library for C

#45
post #44
post #42

Earlier quoted context omitted.

In addition to the problems discussed in the other replies, it's (nearly?) impossible to correctly cancel an operation while blocked on a socket.

Have you tried: * closing the socket (it would be from another, monitoring thread in this case) * setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO) * Would that be different than blocking on select with a an infinite timeout. How do you cancel that? Or are you relying on other sockets getting constant stream of data to wake you up? * do something with an ALARM signal

Closing the socket results in a race condition. You might close the socket, and then another thread opens a new file or socket and happens to get the same fd as your socket used to hold. Now your reader reads from some random unaffiliated fd it shouldn't be touching, causing all sorts of havoc.

A timeout will work fine, but now you're polling, meaning you have an unpleasant tradeoff between efficiency and how long it takes for your thread to notice that it's dead.

Canceling select or any other multi-fd call is really easy. Create a pipe and add it to your fd set. Any time you want the thread to wake up (e.g. because you need to tell it that you're canceling something) you just write to the pipe.

Signals have a similar race condition as closing the socket. If the signal is delivered after you check for cancellation but before you enter the system call, you'll hang.

Re: Dyad: Minimal, portable async networking library for C

#46
post #45
post #44

Earlier quoted context omitted.

Have you tried: * closing the socket (it would be from another, monitoring thread in this case) * setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO) * Would that be different than blocking on select with a an infinite timeout. How do you cancel that? Or are you relying on other sockets getting constant stream of data to wake you up? * do something with an ALARM signal

Closing the socket results in a race condition. You might close the socket, and then another thread opens a new file or socket and happens to get the same fd as your socket used to hold. Now your reader reads from some random unaffiliated fd it shouldn't be touching, causing all sorts of havoc. A timeout will work fine, but now you're polling, meaning you have an unpleasant tradeoff between efficiency and how long it…

> Closing the socket results in a race condition.

That is true. To go more in-depth, you'd do shutdown first. But I think you have to be connected for that.

> Canceling select or any other multi-fd call is really easy. Create a pipe and add it to your fd set. Any time you want the thread to wake up (e.g. because you need to tell it that you're canceling something) you just write to the pipe.

That a good way, agree. But I would still use a select with 2 file descriptors per thread. One fd for the pipe and one for socket itself. Each thread handles its own request and processing as needed without having one global dispatch in the whole application. Pipe is exposed to the outside in case shutdown needs to be triggered (from another thread).

Re: Dyad: Minimal, portable async networking library for C

#47
post #46
post #45

Earlier quoted context omitted.

Closing the socket results in a race condition. You might close the socket, and then another thread opens a new file or socket and happens to get the same fd as your socket used to hold. Now your reader reads from some random unaffiliated fd it shouldn't be touching, causing all sorts of havoc. A timeout will work fine, but now you're polling, meaning you have an unpleasant tradeoff between efficiency and how long it…

> Closing the socket results in a race condition. That is true. To go more in-depth, you'd do shutdown first. But I think you have to be connected for that. > Canceling select or any other multi-fd call is really easy. Create a pipe and add it to your fd set. Any time you want the thread to wake up (e.g. because you need to tell it that you're canceling something) you just write to the pipe. That a good way, agree. B…

2 fds per thread works well. Unfortunately, this means you hit select's performance problems twice over, since the performance scales with the maximum fd you pass it, not the number of fds. But as long as that's OK for what you're doing, it's a nice way to arrange things.
Post reply on HN