Iedereen weet dat Semafoor het baasje van Dommel is, en figureert in de stripreeks, die onder meer in het stripblad Kuifje verscheen in de jaren ’70, en een tekenfilmreeks. Maar er zijn nog andere semaforen op de wereld. Eerst en vooral alle mensen op deze aardbol die voorzien werden van deze voornaam. Spijtig voor hen, maar hierover ga ik het even niet hebben.We hebben het over semaforen in een besturingssysteem.
Voor de onwetenden, een semafoor helpt een programma de toegang tot een gedeelde bron te regelen. Het is een variabele die, met behulp van het OS, door slechts één thread tegelijk verhoogd of verlaagd kan worden. Het helpt bij het oplossen van standaard programmeerproblemen, zoals de gekende “Dining philosophers” die iedere ICT’er wel in zijn oplossing door zijn strot geramd heeft gekregen. Deadlocks hangen hier ook aan vast.
Als doorsnee systeembeheerder kom je weinig in contact met semaforen, aangezien dit op programmaniveau gebruikt wordt, en niet echt veel problemen met zich meebrengt. Velen zullen zelfs niet weten dat dit eigenlijk een zaak is die op kernel-niveau afgehandeld wordt. Af en toe echter kom je deze wel eens tegen.
Semaforen zichtbaar maken en onderzoeken
Onder linux gebruiken we het command ipcs om gedeelde bronnen weer te geven. IPC staat voor “Interprocess communication facilities”. Hieronder een voorbeeldje hoe de uitvoer eruit ziet:
# ipcs
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 8519700 root 600 46084 29 dest
------ Semaphore Arrays --------
key semid owner perms nsems
0x00000000 6979594 nobody 600 1
0x00000000 7012364 nobody 600 1
0x00000000 7143437 nobody 600 1
0x00000000 7176206 nobody 600 1
0x00000000 7208975 nobody 600 1
0x00000000 7241744 nobody 600 1
0x00000000 7307281 nobody 600 1
0x00000000 7340050 nobody 600 1
0x00000000 7372819 nobody 600 1
0x00000000 7405588 nobody 600 1
0x00000000 7438357 nobody 600 1
0x00000000 7471126 nobody 600 1
0x00000000 7503895 nobody 600 1
------ Message Queues --------
key msqid owner perms used-bytes messages
We zien dat er enkele semaforen in gebruik zijn, allemaal door de gebruiker “nobody”. Verder is er ook nog gedeeld geheugen in gebruik. Elke linux heeft het maximaal aantal semaforen vast ingebakken in de kernel. Dit kan ofwel via het /proc filesysteem onderzocht worden, ofwel via het ipcs -l commande (l = limits). We kunnen het ipcs commando limiteren tot enkel de semaforen met de ‘-s‘ vlag.
# ipcs -l -s
------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767
Dit resulteert dus in ietwat uitvoer. Nu moet je weten dat een semafoor in linux eigenlijk een soort array is. De pittige details kan je wel vinden op Google of in een goed boek over kernel internals of OS design, en doen hier niets ter zaken. We zien dat we er 128 voor handen hebben. Met een eenvoudige ipcs zien we deze ook…
Problemen met semaforen
Gisteren botsten we echter op het volgende in mijn apache error log:
semget: No space left on device
Apache start niet meer, en geen enkele manier beweging in te krijgen… ‘Semget’ is natuurlijk ‘semaphore get’, en de “no space on device” is een ietwat vreemde manier om te zeggen dat er geen semaforen meer voor handen zijn. Een ipcs -u (u = usage) gaf aan dat er 128 voor handen waren, en 128 in gebruik waren (ofte “allemaal gebruikt” dus).
# ipcs -u -s
------ Semaphore Status --------
used arrays = 128
allocated semaphores = 128
Allemaal op dus. Een ipcs -s geeft me mooi 128 gebruikte semaforen, allemaal in gebruik door ‘nobody’. Wat was nu het probleem? De apache op de machine had een “semaphore” leak, op het moment dat deze tijdens het starten onderbroken werd. De apache die op deze machine loopt is een ongelukkige erfenis, en kunnen we niet eenvoudig aanpassen (er zijn vergevorderde plannen om de diensten die door deze apache geleverd worden door te schuiven naar een andere machine, zodat we deze eindelijk uit zijn lijden kunnen verlossen). Merk op dat dit slaat op een apache met mod_ssl, en het is het SSL-gedeelte dat dit veroorzaakt.
De oplossing is het verwijderen van deze semaforen. Het commando ipcrm kan dit doen voor u. ‘ipcrm sem ID’ gaat deze resource vrijgeven. Merk op dat, als deze door verschillende processen gebruikt wordt, elk proces onmiddellijk toegang krijgt tot de gedeelde bron. Pas dit toe met zorg! Met ipcs -p -s kan je zien welk process deze semafoor gemaakt heeft, en welke thread deze laatst gebruikt heeft. Verwijderen gaat dus als volgt
# ipcrm sem 6979594
resource(s) deleted
Hierna is deze semafoor terug beschikbaar (controleer met ‘ipcs -u -s‘), en kon apache terug herstart worden.
Extra moeilijkheden in onze setup
Openminds hanteert op enkele machines een vserver setup, welke ervoor zorgt dat we bepaalde servers in een afgeschermde context lopen, en deze processen niet aan andere processen kunnen, wat het idee geeft van een gewone server. Deze technologie werkt heel flexibel, en gebruiken we voor het gemakkellijk manouvreren van systeemresources. Deze technologie toont parrallellen met bvb Xen, User Mode Linux en Virtuozzo. Er is echter slechts een kernel. Misschien ooit meer hierover in een andere post.
Het probleem dat echter ontstond was het feit dat semaforen niet correct vrijgegeven werden in een bepaalde vserver (context), en dat deze vserver achteraf herstart was. Daardoor waren de semaforen hun context kwijt, en konden deze niet meer gezien worden op de vserver (aangezien deze voor het systeem een “andere” was). Bij het tekort aan semaforen vonden we niet meteen waar de grootgebruiker zat, en moesten we dus iets harder op zoek. Het schoot ons te binnen eens te kijken in de “overkoepelende” context, en jawel, daar waren ze te vinden.
# chcontext --ctx 1 ipcs -s
gaf ons alle semaforen, met de correcte userid’s. Zoals reeds gezegd was de apache een erfenis. Alles wat errond hangt was ook een erfenis, en hier hadden we het geluk dat de gebruiker nobody op dat systeem, als welke apache loopt op dat systeem, de ongewone UID van 99 had (en niet 65534 zoals gebruikelijk is). Zo konden eenvoudig alle semaforen die ooit door die gebruiker gemaakt waren, opgespoord worden, en met wat snel scriptwerk eenvoudig verwijderd (lijstje met ipcs -s, grep naar gebruiker 99, cut om enkel het ID veld eruit te filteren, en dan een while-do-done lus met daarin ‘chcontext –ctx 1 ipcrm sem $semid‘)
Zo zie je maar dat het loont je systemen goed te kennen, en alle kantjes ervan door en door te kennen. Semaforen zijn ietwat vage begrippen voor de meeste sysadmins, en veelal kom je er jaren niet mee in contact. Toch is het belangrijk deze ook te kennen, want iets alledaags als Apache kan hier dus voor fouten zorgen.