Fix up struct lxc_container locking
Fix up struct lxc_container locking

1. in container_free, set c->privlock to NULL before calling
sem_destroy, to prevent a window where another thread could call
sem_wait(c->privlock) while c->privlock is not NULL but is already
destroyed.

2. in container_get, check for numthreads < 0 before calling lxclock.
Once numthreads is 0, it never goes back up.

Following is a comment added to lxccontainer.c:

/*
 * Consider the following case:
freer                         |    racing get()er
==================================================================
lxc_container_put()           |   lxc_container_get()
\ lxclock(c->privlock)        |   c->numthreads < 1? (no)
\ c->numthreads = 0           |   \ lxclock(c->privlock) -> waits
\ lxcunlock()                 |   \
\ lxc_container_free()        |   \ lxclock() returns
                              |   \ c->numthreads < 1 -> return 0
\ \ (free stuff)              |
\ \ sem_destroy(privlock)     |

 * When the get()er checks numthreads the first time, one of the following
 * is true:
 * 1. freer has set numthreads = 0.  get() returns 0
 * 2. freer is between lxclock and setting numthreads to 0.  get()er will
 *    sem_wait on privlock, get lxclock after freer() drops it, then see
 *    numthreads is 0 and exit without touching lxclock again..
 * 3. freer has not yet locked privlock.  If get()er runs first, then put()er
 *    will see --numthreads = 1 and not call lxc_container_free().
*/

Signed-off-by: Serge Hallyn <3df611b026e4639bee8aef7a4beb2e39fcebb313@ubuntu.com>
Acked-by: Seth Arnold <3c0aa03eb69ec6f85ce77293321b7c065673f24b@canonical.com>
Acked-by: Stéphane Graber <089afc6d81f66f1168a9849e15660feae286e024@ubuntu.com>

efiop/lxc,raspberrypython/lxc,yubo/lxc,aeris/lxc,ioops/lxc,virajs/lxc,sapun/lxc,lazy404/lxc,regit/lxc,szaszg/lxc,bostjan/lxc,cjwatson/lxc,ioops/lxc,jirislaby/lxc,yubo/lxc,ss1h2a3tw/lxc,GreatFruitOmsk/lxc,DarknessBeforeDawn/lxc,ss1h2a3tw/lxc,smoser/lxc,smoser/lxc,ss1h2a3tw/lxc,thmo/lxc,fwilson42/lxc,smoser/lxc,JohnPeacockMessageSystems/lxc,codebauss/lxc,christiaan/lxc,armcc/lxc,glensc/lxc,ysbnim/lxc,major/lxc,fwilson42/lxc,terceiro/lxc,weizhenwei/lxc,abstrakraft/lxc-android-lxc,rowhit/lxc,rldleblanc/lxc,rowhit/lxc,ysbnim/lxc,raspberrypython/lxc,fwilson42/lxc,bmoar/lxc,thmo/lxc,hkjolhede/lxc,ojkastl/lxc_Patches,bmoar/lxc,JohnPeacockMessageSystems/lxc,codebauss/lxc,christiaan/lxc,Pelagicore/lxc,akshaykarle/lxc,federicobriata/lxc,lisongmin/lxc,hkjolhede/lxc,Ponce/lxc,ojkastl/lxc_Patches,Distrotech/lxc,virajs/lxc,weizhenwei/lxc,DarknessBeforeDawn/lxc,abstrakraft/lxc-android-lxc,QingweiPeterLan/cs188-lxc,szaszg/lxc,terceiro/lxc,Pelagicore/lxc,bmoar/lxc,lazy404/lxc,abstrakraft/lxc-android-lxc,ioops/lxc,ojkastl/lxc_Patches,hfuCN/lxc,ecarrara/lxc,lisongmin/lxc,regit/lxc,aeris/lxc,tych0/lxc,efiop/lxc,smoser/lxc,cjwatson/lxc,virajs/lxc,GreatFruitOmsk/lxc,caglar10ur/lxc,hfuCN/lxc,hallyn/lxc,akshaykarle/lxc,weizhenwei/lxc,glensc/lxc,Ponce/lxc,hallyn/lxc,bostjan/lxc,jirislaby/lxc,Pelagicore/lxc,rowhit/lxc,rldleblanc/lxc,ksperis/lxc,hfuCN/lxc,caglar10ur/lxc,armcc/lxc,JohnPeacockMessageSystems/lxc,sapun/lxc,szaszg/lxc,major/lxc,ojkastl/lxc_Patches,thmo/lxc,major/lxc,rldleblanc/lxc,Ponce/lxc,Distrotech/lxc,jirislaby/lxc,lisongmin/lxc,efiop/lxc,hkjolhede/lxc,lazy404/lxc,LynxChaus/lxc,terceiro/lxc,tych0/lxc,raspberrypython/lxc,codebauss/lxc,GreatFruitOmsk/lxc,tych0/lxc,ksperis/lxc,LynxChaus/lxc,armcc/lxc,aeris/lxc,ecarrara/lxc,Distrotech/lxc,QingweiPeterLan/cs188-lxc,ksperis/lxc,LynxChaus/lxc,federicobriata/lxc,glensc/lxc,yubo/lxc,DarknessBeforeDawn/lxc,hallyn/lxc,sapun/lxc,bostjan/lxc,ysbnim/lxc,abstrakraft/lxc-android-lxc,QingweiPeterLan/cs188-lxc,ecarrara/lxc,regit/lxc,akshaykarle/lxc,cjwatson/lxc,caglar10ur/lxc,federicobriata/lxc,christiaan/lxc