| Author |
Interrupting read() call by SIGALRM in multithreaded application (pthreads)
|
|
| Rafal Krypa 2005-07-26, 5:57 pm |
| I recently have stumbled upon a problem which I think is related to pthreads
and signals. I am writing a driver for fiscal printer receiving commands from
TCP socket. Main thread is blocking on accept() and waiting for new incoming
connections. After opening connection a new thread is spawned to handle that
connection and main thread calls accept() once again.
The connection thread is constantly reading user input by blocking on read()
and each new command received is handled also by separate thread.
Now these threads are communicating with the printer. It is necessary for them
to timeout when reading and writing to the device lasts to long. So I am
installing handler for SIGALRM using sigaction with sa_flags = SA_INTERRUPT, I
call alarm(time) just before read() or write() to the device and... after
receiving SIGALRM by the process only accept() call in main thread is
interrupted.
What am I doing wrong? How can I interrupt read() call?
Everything works as I expected when there is only one thread - I've tried to
remove networking and threads stuff from the application and only call the
function responsible for communication with the printer - then read() call got
interrupted.
I am using glibc 2.3.2 and gcc 3.3.5 (Debian 1:3.3.5-13).
--
/"\ RafalKrypa
\ / ===========
X ASCII Ribbon Campaign
/ \ against HTML mail
| |
| David Schwartz 2005-07-26, 5:57 pm |
|
"Rafal Krypa" <mail@iceberg.pl> wrote in message
news:slrndecjjj.9tb.mail@localhost.localdomain...
>I recently have stumbled upon a problem which I think is related to
>pthreads
> and signals. I am writing a driver for fiscal printer receiving commands
> from
> TCP socket. Main thread is blocking on accept() and waiting for new
> incoming
> connections. After opening connection a new thread is spawned to handle
> that
> connection and main thread calls accept() once again.
> The connection thread is constantly reading user input by blocking on
> read()
> and each new command received is handled also by separate thread.
> Now these threads are communicating with the printer. It is necessary for
> them
> to timeout when reading and writing to the device lasts to long. So I am
> installing handler for SIGALRM using sigaction with sa_flags =
> SA_INTERRUPT, I
> call alarm(time) just before read() or write() to the device and... after
> receiving SIGALRM by the process only accept() call in main thread is
> interrupted.
> What am I doing wrong? How can I interrupt read() call?
> Everything works as I expected when there is only one thread - I've tried
> to
> remove networking and threads stuff from the application and only call the
> function responsible for communication with the printer - then read() call
> got
> interrupted.
> I am using glibc 2.3.2 and gcc 3.3.5 (Debian 1:3.3.5-13).
Don't use signals to interrupt blocking sockets calls in a
multi-threaded program. Use non-blocking sockets and 'select'.
Alternatively. if we're talking TCP, you can interrupt the 'read' call with
'shutdown'. (But that is more complicated to do correctly.)
DS
| |
| Rafal Krypa 2005-07-26, 5:57 pm |
| On 2005-07-26, David Schwartz <davids@webmaster.com> wrote:
> Don't use signals to interrupt blocking sockets calls in a
> multi-threaded program. Use non-blocking sockets and 'select'.
> Alternatively. if we're talking TCP, you can interrupt the 'read' call with
> 'shutdown'. (But that is more complicated to do correctly.)
Thanks a lot for your response. But I don't wand to interrupt a socket call - I
am trying to interrupt read() on character device (serial port).
Do I still have to use select()?
--
/"\ Rafał Krypa
\ / ===========
X ASCII Ribbon Campaign
/ \ against HTML mail
| |
| Rafal Krypa 2005-07-26, 5:57 pm |
| On 2005-07-26, Loic Domaigne <loic-dev@gmx.net> wrote:
> The problem you are faced is due to the POSIX semantic for signal
> delivery in a multi-threaded process. The SIGALRM might be delivered to
> any thread in the process, not necessarily the one that called alarm().
Thank you very much, I finally got it working. 
--
/"\ Rafał Krypa
\ / ===========
X ASCII Ribbon Campaign
/ \ against HTML mail
|
|
|
|