UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

#1 2010-02-25 11:05 PM

adamci
Member
Registered: 2010-02-25
Posts: 3

Re: Waiting for signal or socket data

Hi, I'm a socket newbie, so I apologize for lame questions :-)

I'm trying to implement 2-way communication over a socket. Outbound data are supplied by some worker thread through a shared FIFO (guarded by a mutex certainly). Inbound data from a socket are to be returned to the worker thread through another FIFO. For reasons that I don't want to discuss here, I don't want worker thread to touch sockets. Inbound or outbound data can arrive at any time.

Now the question. Is it possible to have only one thread doing both socket reads and writes without polling? In other words, is it possible to wait for socket inbound data in select() function and at the same time be able to receive signals from the worker thread (signals meaning "new outbound data in FIFO")? In other words, is there a single blocking function capable for waiting on a socket OR a signal (condition variable)? In yet other words, is there an equivalent of Win32's WaitForMultipleObjects?

I was thinking of two solutions:
1. Instead of condition variables, use internal (inter-thread) sockets for signalling between threads. And wait in select() for either socket being readable. But this sounds odd for me. Is it ok?
2. Have two threads: one for socket writes (that one would wait for signals from the worker thread) and one for reads (that would wait in select()). This sounds odd too. In this solution, is there a need for any mutexes guarding access to the socket? When to lock them, when to unlock?

I would appreciate any help.

Regards,
AdamCi.

Offline

#2 2010-02-25 11:43 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: Waiting for signal or socket data

Solution #1 is the way to go IMO.  Use socketpair() (not available under Windows, but it's possible to write your own implementation of it) to create a pair of sockets connected to each other, and then to "signal" the other thread, just write a byte (any byte) to your thread's socket, and that will cause the other thread to drop out of select(), read the byte, and do whatever else you need it to do.

I've been using that technique for years, and it works well for me.  Before I realized I could do that, I also had tried the read_thread+write_thread design, but found it lacking.

Offline

#3 2010-02-26 11:07 AM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,230

Re: Waiting for signal or socket data

adamci;28879 wrote:

Now the question. Is it possible to have only one thread doing both socket reads and writes without polling? In other words, is it possible to wait for socket inbound data in select() function and at the same time be able to receive signals from the worker thread (signals meaning "new outbound data in FIFO")? In other words, is there a single blocking function capable for waiting on a socket OR a signal (condition variable)? In yet other words, is there an equivalent of Win32's WaitForMultipleObjects?


poll/select/epoll/kqueue all work on both sockets and FIFO's, so there is
no need for a signal. But if you get a signal they will be interrupted and
return EINTR.

I was thinking of two solutions:
1. Instead of condition variables, use internal (inter-thread) sockets for signalling between threads. And wait in select() for either socket being readable. But this sounds odd for me. Is it ok?


Yes, but what do you need signalling for?

2. Have two threads: one for socket writes (that one would wait for signals from the worker thread) and one for reads (that would wait in select()). This sounds odd too. In this solution, is there a need for any mutexes guarding access to the socket? When to lock them, when to unlock?


You only need locking if multiple threads do the same operation (read or write)
on the same socket. But doing that makes almost never much sense.

Just add the FIFO and socket to your select/poll set and shuffle data
between them when it arrives, all in one thread. You probably want
to make all file descriptors non-blocking too.

Offline

#4 2010-02-26 03:12 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: Waiting for signal or socket data

Use socketpair()

Unless you need to send 'signals' in both directions, socketpair() is overkill, and
you'd do better to go with pipe()...

But, like i3839 says, I'm not sure why there's a need for ANY additional signalling
method, since you're already dealing with a pipe/FIFO, so you could just add that
directly to the select()/poll()/whatever FDs, and wait directly on that...

Offline

#5 2010-03-01 11:07 PM

adamci
Member
Registered: 2010-02-25
Posts: 3

Re: Waiting for signal or socket data

Thanks i3839 fo your reply.
My program needs to be portable (Win/Linux) so epoll is out of the question, right?
You asked what I need signalling for. I'm not sure if I understant correctly, co I'll clarify what I meant by FIFO. It's a simple class based on std::list/queue.vector/whatever. Worker thread puts data at the end and the socket-talker thread removes data from the head. Each time the worker thread adds new data to the queue, I want it to signal (i.e. notify) the talker thread. Such signal should make the talker thread: wake up from its waiting for socket inbound data, look at new data in the queue, transmit it through the socket and get back to sleep (while waiting for new inbound data).
Or maybe I should do something with the socket, that would invalidate it and thus make the select() call return with an error?
Regards,
AdamCi.

Offline

#6 2010-03-02 12:35 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,230

Re: Waiting for signal or socket data

Yes, epoll is Linux-only. Perhaps libevent works with Windows, or otherwise
use select.

What you call a signal is an event. "Signal" has a different, more specific
meaning already. Same for FIFO: That's a named pipe, and Windows also
supports it (unlike normal pipes). It's clearer to call it a queue. It's confusing
when you mix terminology.

Or maybe I should do something with the socket, that would invalidate it and thus make the select() call return with an error?


No, then you'd lose the socket. Sending a signal would be possible, but
probably not on Windows (I've no idea), but is slow and inefficient anyway.

So your options are more or less limited to what you listed in your initial
post, besides moving to a real FIFO/pipe/socket for communication.

But if you're only communicating with one peer I think the one reader thread
and one writer thread is the simplest solution. The reader just does blocking
reads and the writer does blocking writes. This works fine as long as this is
all you need.

On WIndow's WaitForMultipleObjects is the most efficient solution, its
select() implementation sucks and FIFOs aren't as lightweight as in Linux.
On Linux I'd probably push all data through the pipe and get rid of the
queue, except if you're sending huge amount of data chunks at a time, or
when it's easier to use the queue and only use the pipe for signalling.

Offline

#7 2010-03-02 12:50 PM

adamci
Member
Registered: 2010-02-25
Posts: 3

Re: Waiting for signal or socket data

Thanks for your reply, And sorry for introducing confusion in terminology - as I said, I'm a newbie.
:-)

Offline

#8 2012-04-13 02:45 PM

M.USAMA
Guest

Re: Waiting for signal or socket data

Hi
I want to make a simple packet analyzer which only display the incoming packet header information but i want to do this with Linux signals .Is there any signals which dispatches when  packet arrives on raw sockets.any help will be appreciated.

#9 2012-04-13 04:37 PM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,230

Re: Waiting for signal or socket data

You could use SIGIO, with fcntl(2) and F_SETSIG.

But usually people avoid signals as much as possible
because they're slow, racy and plain annoying to use.

Offline

Board footer

Powered by FluxBB