Multithreading / TCP/IP / Signal-Handling auf 64GB SMP Kernel (2.4) (SuSE Linux 8.2)



  • Das ist keine Library. Das muss in die glibc und in den Kernel eingebaut sein.



  • Ringding schrieb:

    Das ist keine Library. Das muss in die glibc und in den Kernel eingebaut sein.

    Hmmm ... wie finde ich das raus? Hat der 2.4er Kernel native Threads? Im 2.6er sind sie eingebaut.

    D.h. wenn ich zuerst mit der libc linke, muessten die native Threads zuerst drankommen? Leider brauche ich "librt", die wiederum "libpthread" referenziert. Meinst Du, das gibt Probleme?

    EDIT: also muesste -lrt -lc funktionieren... das werd ich morgen mal ausprobieren.



  • NPTL ist erst seit Kernel 2.6 dabei. Einige Distributionen haben es aber nach 2.4 portiert gehabt. RedHat 9 lief zum Beispiel schon mit NPTL.

    Es gilt aber auch für die neue Implementierung, dass man keine pthread_* Funktionen in Signal Handlern aufrufen darf. Das ist so im PThread Standard so geregelt.

    Damit ich keine Signal Handler benutzen muss, nehme ich immer die Lösung mit einem separaten Thread und sigwait, wie es im zitierten Text angedeutet wird.



  • Ponto schrieb:

    NPTL ist erst seit Kernel 2.6 dabei. Einige Distributionen haben es aber nach 2.4 portiert gehabt. RedHat 9 lief zum Beispiel schon mit NPTL.

    Jup, schön war das aber nicht.
    Hat bei mir damals schon ein paar Nachmittage Herumgefluche und nicht eingeplante Überstunden verursacht.



  • Das mit dem sigwait() hoert sich praktikabel an. D.h. ich setze alle betreffenden Signal-Actions auf SIG_IGN und mache einen Extra-Thread mit sigwait(), der dann die anderen benachrichtigt. Das geht dann auch mit SIGSEGV usw., oder? Ich muss solche Ereignisse loggen koennen.

    Gibt es eine Moeglichkeit, eine definierte Initialisierungsreihenfolge von globalen statischen Objekten zu bekommen? Oder gibt's da im GNU nix?

    Das betrifft naemlich die Anforderung, dass die Signal-Handler gesetzt werden muessen, bevor irgendwelche Threads erzeugt werden. Ich habe einige statische Objekte, die selber Threads erzeugen. Sieht so aus, als ob ich den Code auch noch umschreiben muss. 😡

    Haette ehrlich gesagt nicht erwartet, dass Linux dermassen primitiv ist, POSIX-Standard hin oder her. Die haetten's doch so machen koennen wie bei AIX oder Solaris, dass es naemlich noch eine native-Thread-Bibliothek gibt (mit "thr_xxx()" APIs), die NICHT POSIX-konform ist. 🤡

    Hier sind ein paar Gluehbirnen fuer Linux-Kernel-Entwickler: 💡 💡 💡

    Macht doch mal was, was es schon gibt, es gibt auch Buecher ueber Betriebssystemsentwicklung. Und es lohnt sich immer, einen Blick ueber den Tellerrand zu werfen ...



  • Naja, ganz so wie Du tust ist das auch nicht.
    Linux-2.6 ist seit Ewigkeiten heraußen und es gibt eigentlich keinen Grund, das nicht auch zu benutzen; NPTL in den Vanilla-2.4er-Kernel zurückzuportieren wäre ja unsinnig.

    Und von den diversen proprietären Erweiterungen von AIX und Solaris halte ich auch nicht viel, sorgt mittelfristig nur für unportable und schlecht wartbare Programme.



  • Wenn ich aber nur Code fuer Linux schreiben soll, dann kann mir doch egal sein, ob das portabel ist, oder?

    Ausserdem mache ich mir immer portable Bibliotheken, die die Systemspezifika kapseln. UNIX-Programme sind eh nie richtig portabel. Es gibt immer irgendwelche Systemspezifika. Die luegen sich mit ihrem POSIX-Standard in die eigene Tasche -- weil, genauso wie bei Web Standards, nuetzen Standards gar nix, wenn sie nicht von jedem zu 100% umgesetzt werden.

    Noch schlimmer ist, dass wir beim Kunden keine Updates einspielen duerfen. D.h. es werden immer ungepatchte, out-of-the-box-Systeme genommen. Und wir duerfen dem Kunden ja auch nicht vorschreiben, was er zu benutzen hat.

    Deswegen nuetzt es mir gar nix, dass es z.B. in 2.6 NPTL gibt. Auf dem Mars liegen auch interessante Felsbrocken rum. 🤡



  • Power Off schrieb:

    Wenn ich aber nur Code fuer Linux schreiben soll, dann kann mir doch egal sein, ob das portabel ist, oder?

    Für Dich ist das dann scheinbar egal.
    Für Unix an sich wäre das nicht gut, immerhin schreiben verdammt viele Leute primär für GNU/Linux und die BSDler können sich dann mit dem Portieren von interessanten Anwendungen herumschlagen. 👎

    Ausserdem mache ich mir immer portable Bibliotheken, die die Systemspezifika kapseln. UNIX-Programme sind eh nie richtig portabel. Es gibt immer irgendwelche Systemspezifika.

    Ach komm, gerade unter Unix ist es doch verdammt leicht, portabel zu programmieren.
    Dass Du auf Portabilität hinentwickeln musst, muss Dir natürlich klar sein. Dass Du Portabilität auf magische Art und Weise auch bei komplexeren Anwendungen geschenkt bekommst, hast Du ja wohl nicht erwartet, oder?

    Noch schlimmer ist, dass wir beim Kunden keine Updates einspielen duerfen. D.h. es werden immer ungepatchte, out-of-the-box-Systeme genommen. Und wir duerfen dem Kunden ja auch nicht vorschreiben, was er zu benutzen hat.

    Tja, dann muss der Kunde eben die Konsequenzen dafür tragen; wer ungeeignete Werkzeuge verwenden will, der muss sich über die Folgen im Klaren sein.

    Deswegen nuetzt es mir gar nix, dass es z.B. in 2.6 NPTL gibt. Auf dem Mars liegen auch interessante Felsbrocken rum. 🤡

    Eine Reise zum Mars ist aber auch etwas aufwändiger als ein Kernel-Update. (Und ja, ich habe schon genug Kernel-Updates auf Produktionsservern gemacht um das zu wissen.)



  • nman schrieb:

    Noch schlimmer ist, dass wir beim Kunden keine Updates einspielen duerfen. D.h. es werden immer ungepatchte, out-of-the-box-Systeme genommen. Und wir duerfen dem Kunden ja auch nicht vorschreiben, was er zu benutzen hat.

    Tja, dann muss der Kunde eben die Konsequenzen dafür tragen; wer ungeeignete Werkzeuge verwenden will, der muss sich über die Folgen im Klaren sein.

    Genau! Denn Kunden sind immer höchst erfreut, wenn sie eine Software in Auftrag geben und dafür ihr System updaten müssen, damit die darauf läuft.



  • Power Off schrieb:

    Das mit dem sigwait() hoert sich praktikabel an. D.h. ich setze alle betreffenden Signal-Actions auf SIG_IGN und mache einen Extra-Thread mit sigwait(), der dann die anderen benachrichtigt. Das geht dann auch mit SIGSEGV usw., oder? Ich muss solche Ereignisse loggen koennen.

    Gibt es eine Moeglichkeit, eine definierte Initialisierungsreihenfolge von globalen statischen Objekten zu bekommen? Oder gibt's da im GNU nix?

    Das betrifft naemlich die Anforderung, dass die Signal-Handler gesetzt werden muessen, bevor irgendwelche Threads erzeugt werden. Ich habe einige statische Objekte, die selber Threads erzeugen. Sieht so aus, als ob ich den Code auch noch umschreiben muss. 😡

    Die Sache mit sigwait ist ganz gut in: Bradford, Dick, Farrel: Pthreads Programming beschrieben.

    Was soll aber bei einem SIGSEGV geschehen? Wenn ein SIGSEGV auftritt ist der ganze Prozess hinüber und sollte so schnell wie möglich beendet werden, bevor reeller Schaden auftritt. Ich kenne ein paar Spezis bei uns die Threads und einen SIGSEGV Handler gerne benutzen, um bei einem SIGSEGV weitermachen zu können. Man kann versuchen es zu loggen, aber dann sollte auch schon Schluss sein.

    Um die korrekte Initialisierungsreihenfolge zu gewährleisten, solltest du die vorhandenen C++ Mittel benutzen und nicht OS spezifisches. Ich hab gelesen, dass man beim linken für eine korrekte Reihenfolge sorgen kann, weiss aber nicht mehr wie und wo ich es gelesen habe.



  • nman schrieb:

    Für Unix an sich wäre das nicht gut, immerhin schreiben verdammt viele Leute primär für GNU/Linux und die BSDler können sich dann mit dem Portieren von interessanten Anwendungen herumschlagen. 👎

    Meine Software ist aber kein GNU-Paket: Sie ist nicht Open Source. Und wir muessen alle Portierungen selber erledigen (d.h. ich, oder mein Nachfolger, falls es irgendwann einen gibt), falls es auf einer anderen UNIX-Plattform laufen soll.

    Man kann ja durchaus fuer GNU-Pakete vorschreiben, dass sie die POSIX-APIs verwenden muessen. Aber fuer proprietaere Linux-Anwendungen muss das doch nicht so sein, oder?

    Bei AIX und Solaris geht das doch auch. Und AIX hat einen tollen native-Thread API, der wirklich so funktioniert, wie man es erwartet. Bei Solaris ist die native-Thread-Programmierung eher der Horror (frueher zumindest waren sogar einige Systemaufrufe und Bibliotheken bei Solaris nicht multithreadfaehig).

    Die pthread-Library kapselt auch unter Solaris die Tuecken von Solaris nicht, das muss der Programmierer schon selber machen -- und peng, ist die Portabilitaet dahin, da man ueberall "#ifdef" verwenden muss (dann gnade einem Gott, dass man sich selber eine Library geschrieben hat, sonst kann man sich gleich erschiessen).

    Bei GNU/Linux gibt es auch sehr spezifische Probleme, die ausschliesslich unter GNU/Linux auftreten.

    Also von portabler Programmierung auf UNIX-Systemen kann ueberhaupt keine Rede sein.

    Portabel heisst "write once -- run everywhere". Aber selbst Java ist nicht 100%ig portabel. C und C++ ja auch nicht.

    nman schrieb:

    Ach komm, gerade unter Unix ist es doch verdammt leicht, portabel zu programmieren.
    Dass Du auf Portabilität hinentwickeln musst, muss Dir natürlich klar sein. Dass Du Portabilität auf magische Art und Weise auch bei komplexeren Anwendungen geschenkt bekommst, hast Du ja wohl nicht erwartet, oder?

    Nee, das waere ja auch zu schoen, wenn alles auf Anhieb funktionieren wuerde. Dann waeren wir ja arbeitslos ...

    Um aber ein Firmenbudget nicht ueberzustrapazieren, waere es schon geschickt, wenn man sich um solche Probleme nicht kuemmern muesste.

    Ich versuche halt, durch die Entwicklung von Bibliotheken den Portierungsaufwand von Anwendungen zu minimieren.

    Und die Library muss auch auf Windows funktionieren (tut sie bereits).



  • Ponto schrieb:

    Die Sache mit sigwait ist ganz gut in: Bradford, Dick, Farrel: Pthreads Programming beschrieben.

    Was soll aber bei einem SIGSEGV geschehen? Wenn ein SIGSEGV auftritt ist der ganze Prozess hinüber und sollte so schnell wie möglich beendet werden, bevor reeller Schaden auftritt. Ich kenne ein paar Spezis bei uns die Threads und einen SIGSEGV Handler gerne benutzen, um bei einem SIGSEGV weitermachen zu können. Man kann versuchen es zu loggen, aber dann sollte auch schon Schluss sein.

    Um die korrekte Initialisierungsreihenfolge zu gewährleisten, solltest du die vorhandenen C++ Mittel benutzen und nicht OS spezifisches. Ich hab gelesen, dass man beim linken für eine korrekte Reihenfolge sorgen kann, weiss aber nicht mehr wie und wo ich es gelesen habe.

    Danke! 🙂

    Bei SIGSEGV muss ich zumindest noch einen Logeintrag schreiben koennen. Ich habe aber ein asynchrones Logging, d.h. das Log wird von einem Extra-Thread geschrieben. Wenn der Prozess abraucht, fehlen aber u.U. zig bis hunderte von Logeintraegen (die in den betreffenden Millisekunden gequeued wurden).

    Daher muss ich zumindest noch den Rest des Logs rausschreiben koennen. Auch wenn z.B. die Memory-Liste corrupted ist, sonst weiss man ja nicht, was fuer ein Fehler aufgetreten ist.

    Deswegen muss ich auch SIGABRT abfangen, damit irgendwelche Libraries nicht einfach den Prozess beenden koennen.



  • Junge, benutzt mal boost::thread :p



  • Bug schrieb:

    Genau! Denn Kunden sind immer höchst erfreut, wenn sie eine Software in Auftrag geben und dafür ihr System updaten müssen, damit die darauf läuft.

    Denk ab und zu bitte auch mal bevor Du schreibst; darum geht es hier nicht.
    Wenn ein Kunde mir den Auftrag gibt, einen sicheren Terminalserver für eine WindowsXP-Defaultinstallation ohne Service-Packs zu schreiben, dann muss ich diesem Kunden auch sagen, dass das so nicht sinnvoll wäre und er doch bitte mal die ServicePacks installieren soll; andernfalls wird das System einfach nicht wie gewünscht laufen.

    Power Off schrieb:

    Man kann ja durchaus fuer GNU-Pakete vorschreiben, dass sie die POSIX-APIs verwenden muessen. Aber fuer proprietaere Linux-Anwendungen muss das doch nicht so sein, oder?

    Bei AIX und Solaris geht das doch auch. Und AIX hat einen tollen native-Thread API, der wirklich so funktioniert, wie man es erwartet. Bei Solaris ist die native-Thread-Programmierung eher der Horror (frueher zumindest waren sogar einige Systemaufrufe und Bibliotheken bei Solaris nicht multithreadfaehig).

    Der Unterschied ist aber der, dass AIX und Solaris Produkte von kommerziellen Herstellern für kommerzielle Firmen sind. Du erwartest doch wohl hoffentlich nicht, dass die Free Software Community Erweiterungen schreibt, die dem eigenen Projekt/ der Community langfristig nur schaden bzw. keine Vorteile bringen?

    Also von portabler Programmierung auf UNIX-Systemen kann ueberhaupt keine Rede sein.

    Portabel heisst "write once -- run everywhere". Aber selbst Java ist nicht 100%ig portabel. C und C++ ja auch nicht.

    Naja, wenn Du 100%ige Portabilität nicht möglich ist (was Du ja selbst zugibst), dann nimmt man als Maßstab natürlich einfach andere Systeme.
    Und wenn ich daran denke, dass eine für GNU/Linux sauber geschriebene Anwendung normalerweise mit ein paar kleineren Anpassungen ohne weiteres auch auf *BSD, MacOS X, ... läuft, dann ist das doch schon ziemlich gut.

    Ich behaupte hier ja nicht, dass Threading in den 2.4er Kernels toll war, aber immerhin ist das mittlerweile in der auch sonst sehr gelungenen 2.6er-Reihe behoben; was willst Du denn noch?



  • nman schrieb:

    Bug schrieb:

    Genau! Denn Kunden sind immer höchst erfreut, wenn sie eine Software in Auftrag geben und dafür ihr System updaten müssen, damit die darauf läuft.

    Denk ab und zu bitte auch mal bevor Du schreibst; darum geht es hier nicht.
    Wenn ein Kunde mir den Auftrag gibt, einen sicheren Terminalserver für eine WindowsXP-Defaultinstallation ohne Service-Packs zu schreiben, dann muss ich diesem Kunden auch sagen, dass das so nicht sinnvoll wäre und er doch bitte mal die ServicePacks installieren soll; andernfalls wird das System einfach nicht wie gewünscht laufen.

    Doch, darum geht es. Nicht wenige betreiben Systeme, die stabil, speziell angepasst und über einen längeren Zeitpunkt gewachsen sind. Wenn du denen erzählst daß sie's ändern sollen, damit deine Software darauf läuft, hast du einen Kunden weniger. Und du weißt selbst, ein Linux-System zu konfigurieren ist kein Spaß, kein Vergleich mit dem Aufspielen eines Service-Packs unter Windows.



  • Bug schrieb:

    Doch, darum geht es. Nicht wenige betreiben Systeme, die stabil, speziell angepasst und über einen längeren Zeitpunkt gewachsen sind. Wenn du denen erzählst daß sie's ändern sollen, damit deine Software darauf läuft, hast du einen Kunden weniger.

    Es gibt aber nun eben nur diese Möglichkeit, wenn man seine Kunden nicht belügen möchte. Entweder sie installieren sich einen neuen Kernel oder aber ich schreibe meine Software so, dass sie die Features, die bekanntermaßen beim verwendeten System nicht funktionieren, umgeht.

    Aber wenn ich einen derartigen Auftrag angenommen habe, jammern, dass ein uraltes System etwas nicht kann wsa in der aktuellen Version ausgebügelt ist, die noch dazu frei erhältlich ist, läuft einfach nicht. 👎

    Und du weißt selbst, ein Linux-System zu konfigurieren ist kein Spaß, kein Vergleich mit dem Aufpielen eines Service-Packs unter Windows.

    Ach, so ein Schwachsinn.
    Für ein Update auf den 2.6er-Kernel braucht man nicht länger als 20 Minuten pro Rechner. Und danach hat man keine Probleme mit Software die mit 2.6 einfach nicht laufen möchte, wie das bei Windows-Servicepacks oftmals der Fall ist.



  • nman schrieb:

    Aber wenn ich einen derartigen Auftrag angenommen habe, jammern, dass ein uraltes System etwas nicht kann wsa in der aktuellen Version ausgebügelt ist, die noch dazu frei erhältlich ist, läuft einfach nicht. 👎

    Ich jammer ja gar nicht -- ich weiss, dass die Software auf dem 2.4er Kernel laufen muss.

    Update vom Kundenrechner ist ausgeschlossen, da wir ja sonst das System nicht mehr fuer SuSE Linux 8.2 anbieten koennen.



  • Für ein Update auf den 2.6er-Kernel braucht man nicht länger als 20 Minuten pro Rechner. Und danach hat man keine Probleme mit Software die mit 2.6 einfach nicht laufen möchte.

    Und was ist, wenn der Kunde proprietäre Software verwendet, die nur mit genau dieser Version läuft (weil sie z.B. irgendwelche Furz-Binary-Only-Kernelmodule verwendet? Jede größere Firma verwendet haufenweise solchen Dreck, da kann man kaum was dagegen tun.

    Außerdem ist das Upgraden auf NPTL so gut wie unmöglich. Man muss eigentlich ein komplettes Distributionsupdate machen, wenn die Distro das kann.



  • Ringding schrieb:

    Und was ist, wenn der Kunde proprietäre Software verwendet, die nur mit genau dieser Version läuft (weil sie z.B. irgendwelche Furz-Binary-Only-Kernelmodule verwendet? Jede größere Firma verwendet haufenweise solchen Dreck, da kann man kaum was dagegen tun.

    Naja, wenn solcher Dreck wichtig ist, dann hat man dafür einen Wartungsvertrag und bekommt vom Hersteller auch aktuelle Variante.
    Ist aber ein guter Punkt, derartige Sachen begegnen mir in meinem Umfeld normalerweise eher nicht.

    Außerdem ist das Upgraden auf NPTL so gut wie unmöglich. Man muss eigentlich ein komplettes Distributionsupdate machen, wenn die Distro das kann.

    Normalerweise sollte ein entsprechendes libc-Update völlig ausreichen.

    Power Off schrieb:

    Ich jammer ja gar nicht -- ich weiss, dass die Software auf dem 2.4er Kernel laufen muss.

    Sorry, es klang einfach so. Wenn man Windows-Usern vorwirft, was für Schrott WinME ist, dann sagen die einem ja auch (völlig zu Recht), dass man Windows aber nicht an einer so alten Version messen kann.



  • derartige Sachen begegnen mir in meinem Umfeld normalerweise eher nicht.

    Sei froh...

    Ein Kunde von uns hat RHEL 2.1 laufen mit einem ganzen Haufen von proprietärer Compaq-Software, von der ich nicht weiß, was sie tut. Ist ebenfalls ein altes System ohne NPTL, und dieses Compaq-Zeug hat ein kräftiges memory leak, sodass es ca. einmal im Monat neu gestartet werden muss. Unsere Serveranwendung läuft aber erstaunlicherweise ziemlich stabil darauf, obwohl sie Threads verwendet.


Anmelden zum Antworten