Go to file
Chandra Penke a2eca3b19d Fix for Race condition can hang miniserver thread.
Add 'requiredThreads' field to the ThreadPool structure, to avoid
a race condition when waiting for a new thread to be created. The
race condition occurs when a thread is destroyed while the master
thread is waiting for a new thread to be created.

Thanks to Chuck Thomason for pointing the problem.

Summary: Race condition can hang miniserver thread - ID: 3158591

Details:
Hello,

I have found a race condition in the thread pool handling of
libupnp-1.6.6 that periodically results in the miniserver thread
getting blocked infinitely.

In my setup, I have the miniserver thread pool configured with 1
job per thread, 2 threads minimum, and 50 threads maximum.

Just before the lockup occurs, the miniserver thread pool contains
2 threads: one worker thread hanging around from a previous HTTP
request job (let's call that thread "old_worker") and the
miniserver thread itself.

A new HTTP request comes in. Accordingly, the miniserver enters
schedule_request_job() and then ThreadPoolAdd(). In
ThreadPoolAdd(), the job gets added to the medium-priority queue,
and AddWorker() is called. In AddWorker(), jobs = 1 and threads =
1, so CreateWorker gets called.

When we enter CreateWorker(), tp->totalThreads is 2, so
currentThreads is 3. The function creates a new thread and then
blocks on tp->start_and_shutdown. The miniserver thread expects
the newly created thread to increment tp->totalThreads and then
signal the condition variable to wake up the miniserver thread and
let it proceed.

The newly created thread starts in the WorkerThread() function. It
increments tp->totalThreads to 3, does a broadcast on the
start_and_shutdown condition, and starts running its job. However,
before the miniserver thread wakes up, "old_worker" times out. It
sees that there are no jobs in any queue and that the total number
of threads (3) is more than the minimum (2). As a result, it
reduces tp->totalThreads to 2 and dies.

Now the miniserver thread finally wakes up. It checks
tp->totalThreads and sees that its value is 2, so it blocks on
tp->start_and_shutdown again. It has now "missed" seeing
tp->totalThreads get incremented to 3 and will never be unblocked
again.

When this issue does occur for a server device, the miniserver
port remains open, but becomes unresponsive since the miniserver
thread is stuck. SSDP alive messages keep getting sent out, as
they are handled by a separate thread. Reproducing the issue is
difficult due to the timing coincidence involved, but in my
environment I am presently seeing it at least once a day. I
figured out the sequence described above through addition of my
own debug logs.

The relevant code involved in this bug has not changed
substantially in libupnp-1.6.10, though I am planning to test
against 1.6.10 as well in the near future.

Do you have any input for an elegant fix for this issue?

Thanks,

Chuck Thomason
(cherry picked from commit c4e9757bcf)
2011-01-20 04:46:57 -02:00
build Define _FILE_OFFSET_BITS, _LARGEFILE_SOURCE and _LARGE_FILE_SOURCE in upnpconfig.h. 2011-01-16 22:39:37 -02:00
docs/dist SF Patches Tracker [ 1865812 ] typo in docs comment 2008-01-07 12:02:33 +00:00
ixml samples: Fix compiler warnings. 2010-11-17 12:01:04 -02:00
m4 Workaround for a problem with the new automake AM_CONDITIONAL macro 2008-01-23 11:59:30 +00:00
threadutil Fix for Race condition can hang miniserver thread. 2011-01-20 04:46:57 -02:00
upnp Fix for typo in strndup() function definition. 2011-01-17 09:04:51 -02:00
.gitignore Remove "upnp_" prefix from samples. 2010-11-17 23:35:07 -02:00
AUTHORS Removing unnecessary additional directory level. 2006-07-04 02:44:17 +00:00
bootstrap SF Tracker [ 1703533 ] Patch to make it compile under FreeBSD 2007-04-28 17:45:34 +00:00
ChangeLog Fix for Race condition can hang miniserver thread. 2011-01-20 04:46:57 -02:00
configure.ac Use config.h to test for the availability of strndup() and strnlen(). 2011-01-16 21:06:00 -02:00
COPYING Removing unnecessary additional directory level. 2006-07-04 02:44:17 +00:00
Doxyfile Doxygen. 2008-06-10 03:23:08 +00:00
INSTALL Removing unnecessary additional directory level. 2006-07-04 02:44:17 +00:00
libupnp.pc.in Add PTHREAD_CFLAGS to Libs: in libupnp.pc, as assumed by acx_pthread.m4 2010-05-14 13:09:22 +00:00
libupnp.spec Fixed spec version. 2010-10-04 11:48:25 -03:00
LICENSE Removing unnecessary additional directory level. 2006-07-04 02:44:17 +00:00
Makefile.am UTF-8. 2010-10-04 11:39:50 -03:00
NEWS Removing unnecessary additional directory level. 2006-07-04 02:44:17 +00:00
README Update the documentation about samples in README. 2011-01-17 11:37:45 -02:00
svnignore Moved upnp_tv_ctrlpt and upnp_tv_device executables from folder 2007-05-11 05:00:43 +00:00
THANKS Update the documentation about samples in README. 2011-01-17 11:37:45 -02:00
TODO Updated TODO list. 2010-10-04 11:30:28 -03:00

Portable SDK for UPnP* Devices (libupnp)

Copyright (c) 2000-2003 Intel Corporation - All Rights Reserved.
Copyright (c) 2005-2006 Rémi Turboult <r3mi@users.sourceforge.net>
Copyright (c) 2006 Michel Pfeiffer and others <virtual_worlds@gmx.de>

See LICENSE for details.

This file contains information about the above product in the following 
sections: 

1.  Release Contents
2.  Package Contents
3.  System Requirements
4.  Build Instructions
5.  Install/Uninstall Instructions
6.  Product Release Notes
7.  New Features
8.  Support and Contact Information


1) Release Contents
-------------------------------------------

The Portable SDK for UPnP Devices is an SDK for development of UPnP device 
and control point applications.  It consists of the core UPnP 
protocols along with a UPnP-specific eXtensible Markup Language (XML) parser 
supporting the Document Object Model (DOM) Level 2 API and an optional, 
integrated mini web server for serving UPnP related documents.


2) Package Contents
-------------------------------------------

The SDK for UPnP Devices contains the following: 

README    	This file.  Contains the installation and build instructions.
LICENSE   	The licensing terms the SDK is distributed under.
NEWS		Changes and new features.
ixml\doc	The files for generating the XML parser documentation from
		the source code.
ixml\inc	The public include files required to use the XML parser.
ixml\src	The source code to the XML parser library.
threadutil\inc	The public include files required to the threading 
		utility library.
threadutil\src	The source code to the threading utility library.
upnp\doc	The files for generating the SDK documentation from the
		source code.
upnp\inc	The public include files required to use the SDK.
upnp\src      	The source files comprising the SDK, libupnp.so.
upnp\sample	A sample device and control point application, illustrating the
          	usage of the SDK.


3) System Requirements
-------------------------------------------

The SDK for UPnP Devices is designed to compile and run under several
operating systems.  It does, however, have dependencies on some
packages that may not be installed by default.  All packages that it
requires are listed below.

libpthread  The header and library are installed as part of the glibc-devel
            package (or equivalent).

Additionally, the documentation for the SDK can be auto-generated from 
the UPNP.H header file using DOC++, a documentation system for C, C++, 
IDL, and Java*.  DOC++ generates the documentation in HTML or TeX format.
Using some additional tools, the TeX output can be converted into a
PDF file.  To generate the documentation these tools are required:

DOC++       The homepage for DOC++ is http://docpp.sourceforge.net/.
            The current version as of this release of the SDK is
            version 3.4.9.  DOC++ is the only requirement for generating
            the HTML documentation.
LaTeX/TeX   To generate the PDF documentation, LaTeX and TeX tools are
            necessary.  The tetex and tetex-latex packages provide these
            tools.
dvips       dvips converts the DVI file produced by LaTeX into a PostScript*
            file.  The tetex-dvips package provides this tool.
ps2pdf      The final step to making the PDF is converting the PostStript
            into Portable Document Format.  The ghostscript package provides
            this tool.

For the UPnP library to function correctly, networking must be configured
properly for multicasting.  To do this:

route add -net 239.0.0.0 netmask 255.0.0.0 eth0

where 'eth0' is the network adapter that the UPnP library will use.  Without
this addition, device advertisements and control point searches will not
function.



4) Build Instructions
-------------------------------------------

CORE LIBRARIES

The in the examples below, replace $(LIBUPNP) with "libupnp-x.y.z",
with x, y, and z corresponding to the version of the library that you have.

All pieces of the SDK are configured and built from the $(LIBUPNP) directory. 

% cd $(LIBUPNP)
% ./configure
% make

will build a version of the binaries without debug support, and with default 
options enabled (see below for options available at configure time).

% cd $(LIBUPNP)
% ./configure CFLAGS="-DSPARC_SOLARIS -mtune=<cputype> -mcpu=<cputype>"
% make

will build a Sparc Solaris version of the binaries without debug support
and with default options enabled (see below for options available at
configure time). Please note: <cputype> has to be replaced by a token that
fits to your platform and CPU (e.g. "supersparc").

To build the documentation, assuming all the necessary tools are installed 
(see section 3) :

To generate the HTML documentation:

% cd $(LIBUPNP)
% make html

To generate the PDF file:

% cd $(LIBUPNP)
% make pdf


A few options are available at configure time. Use "./configure --help"
to display a complete list of options. Note that these options 
may be combined in any order.
After installation, the file <upnp/upnpconfig.h> will provide a summary
of the optional features that have been included in the library.


% cd $(LIBUPNP)
% ./configure --enable-debug
% make 

will build a debug version with symbols support.

To build the library with the optional, integrated mini web server (note
that this is the default):

% cd $(LIBUPNP)
% ./configure --enable-webserver
% make 

To build without:

% cd $(LIBUPNP)
% ./configure --disable-webserver
% make 


The SDK also contains some additional helper APIs, declared in
inc/tools/upnptools.h.  If these additional tools are not required, they can
be compiled out:

% cd $(LIBUPNP)
% ./configure --disable-tools
% make 

By default, the tools are included in the library.

To further remove code that is not required, the library can be build with or 
with out the control point (client) or device specific code.  To remove this
code:

% cd $(LIBUPNP)
% ./configure --disable-client
% make 

to remove client only code or:

% cd $(LIBUPNP)
% ./configure --disable-device
% make 

to remove device only code.

By default, both client and device code is included in the library.  The
integrated web server is automatically removed when configuring with 
--disable-device.

To build the library without large-file support (enabled by default) :

% cd $(LIBUPNP)
% ./configure --disable-largefile
% make 


To remove all the targets, object files, and built documentation:

% cd $(LIBUPNP)
% make clean


CROSS COMPILATION

To cross compile the SDK, a special "configure" directive is all that is
required:

% cd $(LIBUPNP)
% ./configure --host=arm-linux
% make

This will invoke the "arm-linux-gcc" cross compiler to build the library.


SAMPLES

The SDK contains two samples: a TV device application and a control point
that talks with the TV device.  They are found in the $(LIBUPNP)/upnp/sample 
directory.  

To build the samples (note: this is the default behaviour):

% cd $(LIBUPNP)
% ./configure --enable-samples
% make

will build the sample device "$(LIBUPNP)/upnp/tv_device" and
sample control point "$(LIBUPNP)/upnp/tv_ctrlpt". 
Note : the sample device won't be built if --disable-device has been 
configured, and the sample control point won't be build if --disable-client 
has been configured.

To run the sample device, you need to create a tvdevice directory and move
the web directory there, giving: "$(LIBUPNP)/upnp/sample/tvdevice/web".
To run the sample invoke from the command line as follows:

% cd $(LIBUPNP)/upnp/sample/tvdevice
% ../tv_device



SOLARIS BUILD

The building process for the Solaris operating system is similar to the one
described above. Only the call to ./configure has to be done using an
additional parameter:

./configure CFLAGS="-mcpu=<cputype> -mtune=<cputype> -DSPARC_SOLARIS"

where <cputype> has to be replaced by the appropriate CPU tuning flag (e.g.
"supersparc"). Afterwards

make
make install

can be called as described above.



WINDOWS BUILD

In order to build libupnp under Windows the pthreads-w32 package is required.
You can download a self-extracting ZIP file from the following location:

ftp://sources.redhat.com/pub/pthreads-win32/pthreads-w32-2-7-0-release.exe

Execute the self-extracting archive and copy the Pre-build.2 folder to the
top level source folder.
Rename Pre-build.2 to pthreads. 
Open the provided workspace build\libupnp.dsw with Visual C++ 6.0 and select
Build->Build libupnp.dll (F7)

For building a static library instead of a DLL and for using the static
pthreads-w32 library following switches need to be defined additionally:

UPNP_STATIC_LIB - for creating a statically linkable UPnP-library
PTW32_STATIC_LIB - for using the static pthreads32 library


5) Install/Uninstall Instructions
-------------------------------------------

Install

The top-level makefile for the UPnP SDK contains rules to install the 
necessary components.  To install the SDK, as root:

make install

Uninstall

Likewise, the top-level makefile contains an uninstall rule, reversing 
the steps in the install:

make uninstall


6) Product Release Notes
-------------------------------------------

The SDK for UPnP Devices v1.2.1a has these known issues:

- The UPnP library may not work with older versions of gcc and libstdc++, 
  causing a segmentation fault when the library loads.  It is recommended
  that gcc version 2.9 or later be used in building library.
- The UPnP library does not work the glibc 2.1.92-14 that ships with
  Red Hat 7.0.  For the library to function, you must updated the glibc
  and glibc-devel packages to 2.1.94-3 or later.  There is some issue with
  libpthreads that has been resolved in the 2.1.94 version.


7) New Features
-------------------------------------------

See NEWS file.


8) Support and Contact Information
-------------------------------------------

Intel is not providing support for the SDK for UPnP Devices. Mailing lists
and discussion boards can be found at http://www.libupnp.org/.

If you find this SDK useful, please send an email to upnp@intel.com and let
us know.


* Other brands, names, and trademarks are the property of their respective 
owners.