Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Verständnisfrage zu fork()

7 views
Skip to first unread message

Heinz-Mario Frühbeis

unread,
Apr 16, 2013, 6:57:43 AM4/16/13
to
Hallo zusammen!

main >
#include "ida.h"
int main(){
IDA m_IDA("Hallo", mLzStat);
return mLzStat;
}

ida.h >
IDA::IDA(std::string vOwner, int &vLzStat){
std::cout<<"\nHallo"; //Hier wird "Hallo" zweimal ausgegeben [1]
std::cout.flush();
RunIDA("Name");
}

pid_t IDA::RunIDA(std::string vName){
pid_t nPID, nRetPID;
structIDAReg nStruct;
switch(nPID = fork()){
case -1 :
break;
case 0:
nRetPID = getpid();
break;
default:
if (waitpid (nPID_IDABase, NULL, 0) != nPID_IDABase) {
return getpid();
}
}
return getpid();
}

[1] Hier verstehe ich nicht wieso zweimal "Hallo" ausgegeben wird.
Wenn ich aber in IDA::IDA() noch eine weitere Funktion aufrufe eines
anderen Headers und in dieser Funktion ein std::cout eintrage, dann wird
dort nur einmal das std::cout ausgegeben.

Wird denn tatsᅵchlich der Konstruktor von IDA zweimal aufgerufen, was
aber eigentlich nicht kann, denn sonst mᅵᅵte ja auch in einer anderen
Funktion eines anderen Headers zweimal eine Ausgabe erfolgen?

Meine Frage: Wieso ist das so?
Und wie handelt man das am Besten?
Muss man dann quasi seperieren nach pid_t, oder wie?

Ich hoffe, das ihr mich da auf den richtigen Weg bringen kᅵnnt.

Mit Gruᅵ
Heinz-Mario Frᅵhbeis

Heinrich Wolf

unread,
Apr 16, 2013, 10:16:02 AM4/16/13
to
Das ist aber nicht der gesamte Code.
Wie ist die Klasse IDA aufgebaut?

Edzard Egberts

unread,
Apr 16, 2013, 10:19:18 AM4/16/13
to
Heinrich Wolf schrieb:
> Das ist aber nicht der gesamte Code.
> Wie ist die Klasse IDA aufgebaut?

Da bin ich auch nicht durchgestiegen! :o)

Vermutlich geht es aber sowieso eher um eine Verstᅵndnisfrage zum
generischen Kopierkonstruktor.

Rainer Weikusat

unread,
Apr 16, 2013, 11:20:55 AM4/16/13
to
Normalerweise waere die Erklaerung: 'std::cout << "Hallo"' schreibt
den String in den cout-Puffer. In Folge des forks werden aus diesem
einen Puffer zwei Puffer, die bei Beendigung der jeweiligen Prozesse
beide geflusht werden. Um solche Phaenomene zu vermeiden, sollte man
einen der beiden Prozesse via _exit beenden.

Allerdings passt das nicht mit dem cout.flush() zusammen. Es waere
hilfreich, wenn Du etwas posten wuerdest, dass man uebersetzen und
ausfuehren kann und so den 'Fehler' hervorrufen.

Heinz-Mario Frühbeis

unread,
Apr 16, 2013, 12:15:19 PM4/16/13
to
Hallo!
Das mit dem std::cout.flush() habe ich aus dem Internet.

Irgendwie ist bei mir der Wurm drin :(
Ich kam durch dein Posting auf die Idee, da� mal soweit zu k�rzen als
m�glich. Und pl�tzlich kam als Ausgabe nur einmal "Hallo".
Dann habe ich ein bisschen erweitert und wieder: Nur einmal "Hallo".
Dann habe ich es wieder komplett gemacht und wieder: Nur einmal "Hallo".

Und ich habe keine Ahnung, was ich da jetzt ver�ndert habe, denn nun
bekomme ich:
HALLO //IDA Konstruktor
PARENT // Parent Prozess
CHILD // Child Prozess
4 // Eine weitere Funktion eines anderen Headers
AUSGABE 2 // Der Child Prozess intern; ein Timer mit Callback
AUSGABE 1 //
AUSGABE 0 //
OUT // Programm Ende

Jetzt m��te ich wohl so was schreiben, wie "Entschuldigung, f�r die
St�rung".

Also nichts f�r ungut.
Mit Gru�
Heinz-Mario Fr�hbeis

Heinz-Mario Frühbeis

unread,
Apr 17, 2013, 6:11:52 AM4/17/13
to
Am 16.04.2013 17:20, schrieb Rainer Weikusat:
Es lag am std::cout.flush().
Wenn man es irgendwo "vergißt", dann wird das doppelt ausgegeben.

Ich schätze mal, daß ich Danke sage :)

Das mit dem "_exit" muss ich noch schauen, da ich noch gar nicht weiß,
wie das jetzt alles so im Einzelnen abläuft und weil da noch einige
forks() zur Laufzeit hinzukommen. Is' aber quasi im Hinterkopf.

Mit Gruß
Heinz-Mario Frühbeis

Marcel Müller

unread,
May 3, 2013, 6:55:47 AM5/3/13
to
Hallo!

On 16.04.13 12.57, Heinz-Mario Fr�hbeis wrote:
> IDA::IDA(std::string vOwner, int &vLzStat){
> std::cout<<"\nHallo"; //Hier wird "Hallo" zweimal ausgegeben [1]
> std::cout.flush();
> RunIDA("Name");
> }

mal eine andere Frage. Ist eigentlich C++ und fork mittlerweile safe?
Ich habe noch gelernt, dass dies undefiniertes Verhalten ist. Das
undefiniertes Verhalten den Fall mit einschlie�t, dass es auch wie
erwartet geht, w�re ja nichts Neues.

Wei� jemand dazu n�heres?


Marcel

Rainer Weikusat

unread,
May 3, 2013, 10:06:46 AM5/3/13
to
Marcel M�ller <news.5...@spamgourmet.org> writes:
> On 16.04.13 12.57, Heinz-Mario Fr�hbeis wrote:
>> IDA::IDA(std::string vOwner, int &vLzStat){
>> std::cout<<"\nHallo"; //Hier wird "Hallo" zweimal ausgegeben [1]
>> std::cout.flush();
>> RunIDA("Name");
>> }
>
> mal eine andere Frage. Ist eigentlich C++ und fork mittlerweile safe?
> Ich habe noch gelernt, dass dies undefiniertes Verhalten ist.

Aus schlichten praktischen Gruenden ist jegliche Interaktion zwischen
einem betriebsystemspezifischen Interface und 'irgendeinem
ISO-Sprachstandard' (bzw von diesem spezifizierten Dingen) aus Sicht
des ISO-Standards 'undefiniertes Verhalten' weil die besagte
Sprachnorm eine betriebssystemunabhaengige Sprache definiert und kein
Betriebsystem. Undefiniert ist hier einfach woertlich zu verstehen,

> Das undefiniertes Verhalten den Fall mit einschlie�t,

naemlich als 'nicht definiert' und nicht, wie es der populaere
Irrglaube moechte, als 'irgenetwas nicht vorhersagbares und total
irrsinniges wird passieren' (das waere eine - wenn auch sehr vage -
Definition).

Marcel Müller

unread,
May 3, 2013, 11:20:41 AM5/3/13
to
On 03.05.13 16.06, Rainer Weikusat wrote:
> Marcel M�ller<news.5...@spamgourmet.org> writes:
>> mal eine andere Frage. Ist eigentlich C++ und fork mittlerweile safe?
>> Ich habe noch gelernt, dass dies undefiniertes Verhalten ist.
>
> Aus schlichten praktischen Gruenden ist jegliche Interaktion zwischen
> einem betriebsystemspezifischen Interface und 'irgendeinem
> ISO-Sprachstandard' (bzw von diesem spezifizierten Dingen) aus Sicht
> des ISO-Standards 'undefiniertes Verhalten' weil die besagte
> Sprachnorm eine betriebssystemunabhaengige Sprache definiert und kein
> Betriebsystem. Undefiniert ist hier einfach woertlich zu verstehen,

Ich habe meine Frage vielleicht nicht klar ausgedr�ckt. Ich meinte schon
bezogen auf konkrete Implementierungen, wie z.B. gcc.


Marcel

Edzard Egberts

unread,
May 3, 2013, 11:38:16 AM5/3/13
to
Marcel M�ller schrieb:
> mal eine andere Frage. Ist eigentlich C++ und fork mittlerweile safe?
> Ich habe noch gelernt, dass dies undefiniertes Verhalten ist.

Kommt mir ja schon etwas komisch vor, was meinst Du �berhaupt mit
"safe"? Threadsafe? Forksafe?

So wie ich das verstehe, ist fork() ein Systemaufruf und f�r einen
Systemaufruf gibt es eine Konvention, die eingehalten werden muss. Der
eigentliche Fork-Vorgang, wird vom Betriebssystem erledigt und hat
nichts mit der Programmiersprache zu tun. Schlie�lich ist C++ eine
Hochsprache und wird beim Compilieren in die jeweilige Maschinensprache
umgesetzt - der "symbolische Aufruf" also in die richtige Konvention und
Register�bergabe (etc.) �bersetzt. Warum eine derartige �bersetzung aus
C++ undefinierter sein soll, als aus irgend einer anderen
Programmiersprache, ist mir nicht ersichtlich. Da k�nnte ich mir doch
genau so gut Sorgen machen, ob ein Intel-Prozessor besser forkt, als ein
AMD?

Gerald Breuer

unread,
May 3, 2013, 12:16:04 PM5/3/13
to
Am 03.05.2013 17:38, schrieb Edzard Egberts:

> So wie ich das verstehe, ist fork() ein Systemaufruf und f�r einen
> Systemaufruf gibt es eine Konvention, die eingehalten werden muss.
> Der eigentliche Fork-Vorgang, wird vom Betriebssystem erledigt und
> hat nichts mit der Programmiersprache zu tun. ...

Also C++ hat mittlerweie Threads, und wenn ich da Mutexe oder Condi-
tion-Variablen nutze die z.T. auf Kernel-Resourcen aufbauen die beim
erstellen des neuen Prozesses nicht dupliziert werden wird's Probleme
geben.


Rainer Weikusat

unread,
May 3, 2013, 12:21:01 PM5/3/13
to
'Eine konkrete Implementierung' kann undokumentiertes Verhalten haben
aber kein undefiniertes. Worauf hast Du Dich denn konkret bezogen?
Google meint 'nichts spezifisches' zu diesem Thema.

Rainer Weikusat

unread,
May 3, 2013, 12:35:29 PM5/3/13
to
Das ist Bloedsinn (es impliziert, das der fork-Systemaufruf selber
nicht funktioniert).

NB: Du kannst Dir Deine ueblichen Schimpfkanonaden ("Hau Deinem
Vorposter bitte aufs Maul") ersparen.

Stefan Reuther

unread,
May 3, 2013, 1:46:11 PM5/3/13
to
Rainer Weikusat wrote:
> Gerald Breuer <Gerald...@googlemail.com> writes:
>>Am 03.05.2013 17:38, schrieb Edzard Egberts:
>>>So wie ich das verstehe, ist fork() ein Systemaufruf und f�r einen
>>>Systemaufruf gibt es eine Konvention, die eingehalten werden muss.
>>>Der eigentliche Fork-Vorgang, wird vom Betriebssystem erledigt und
>>>hat nichts mit der Programmiersprache zu tun. ...
>>
>>Also C++ hat mittlerweie Threads, und wenn ich da Mutexe oder Condi-
>>tion-Variablen nutze die z.T. auf Kernel-Resourcen aufbauen die beim
>>erstellen des neuen Prozesses nicht dupliziert werden wird's Probleme
>>geben.
>
> Das ist Bloedsinn (es impliziert, das der fork-Systemaufruf selber
> nicht funktioniert).

Das ist kein Bl�dsinn, sondern genau das Problem.

Es gibt mindestens ein Betriebssystem mit POSIX-Bapper, bei dem fork()
nach einem pthread_create() immer nur noch EAGAIN liefert: QNX.

Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
die in einem C++-Programm gerne mal implizit benutzt werden, sind da
nicht darunter.

Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
sind: falls den ein anderer Thread gerade hat, kann man nur verlieren.
Der Kindprozess k�nnte also, hinreichend br�sige Bibliothek voraus-
gesetzt, an der "}" nach dem fork() h�ngen bleiben beim Wegr�umen
irgendeines C++-Objekts. Grund genug, es f�r "nicht funktionierend" zu
halten.

Praktisch machen sich einige Bibliothekshersteller nat�rlich mehr M�he
als die oben zitierten Kanadier.


Stefan

Rainer Weikusat

unread,
May 3, 2013, 3:11:34 PM5/3/13
to
Stefan Reuther <stefa...@arcor.de> writes:
> Rainer Weikusat wrote:
>> Gerald Breuer <Gerald...@googlemail.com> writes:
>>>Am 03.05.2013 17:38, schrieb Edzard Egberts:
>>>>So wie ich das verstehe, ist fork() ein Systemaufruf und f�r einen
>>>>Systemaufruf gibt es eine Konvention, die eingehalten werden muss.
>>>>Der eigentliche Fork-Vorgang, wird vom Betriebssystem erledigt und
>>>>hat nichts mit der Programmiersprache zu tun. ...
>>>
>>>Also C++ hat mittlerweie Threads, und wenn ich da Mutexe oder Condi-
>>>tion-Variablen nutze die z.T. auf Kernel-Resourcen aufbauen die beim
>>>erstellen des neuen Prozesses nicht dupliziert werden wird's Probleme
>>>geben.
>>
>> Das ist Bloedsinn (es impliziert, das der fork-Systemaufruf selber
>> nicht funktioniert).
>
> Das ist kein Bl�dsinn, sondern genau das Problem.

Wenn man sowohl 'C++' als auch 'Kernel-Resourcen' mal grosszuegig
unter den Tisch fallen laessst bzw 'Kernel-Resourcen' inkorrekt als
'threads' interpretiert, dann kann man die oA Aussage einen Sinn
_hineinlesen_[*] und zwar 'UNIX(*) definiert (praktisch) kein sinnvolles
Verhalten fuer Prozesse, die sowohl multi-threaded sind als auch fork
benutzen'.

> Es gibt mindestens ein Betriebssystem mit POSIX-Bapper, bei dem fork()
> nach einem pthread_create() immer nur noch EAGAIN liefert: QNX.

Es gibt vermutlich noch mehr fehlerhafte[*] POSIX-Implementierungen aber
mit 'C++' hat das nichts zu tun.

[*] 'The system lacked the necessary resources to create
another process' kann das nicht sein.

> Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
> und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
> die in einem C++-Programm gerne mal implizit benutzt werden, sind da
> nicht darunter.

Das ist zum einen nicht richtig:

A process shall be created with a single thread. If a
multi-threaded process calls fork(), the new process shall
contain a replica of the calling thread and its entire address
space, possibly including the states of mutexes and other
resources. Consequently, to avoid errors, the child process
may only execute async-signal-safe operations until such time
as one of the exec functions is called.

und zum anderen nicht relevant: Auf der abstrakten Ebene eines
Betriebssystem-Interfacestandards koennen keine Aussagen ueber das
Verhalten konkreter Anwendungen im Zusammenspiel mit konkreten
Implementierungen gemacht werden.

> Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
> Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
> sind:

Fork kann das ganz wunderbar. 'Das Problem' ist hier das Verhalten,
dass die UNIX(*)-Norm fuer 'Mutex-Objekte' fordert, naemlich dass
diese nur von dem thread, dem sie gehoeren, wieder freigegeben werden
koennen. Wenigstens fuer Linux wird das von der C-Library dadurch
sichergestellt, dass die Bibliotheksroutine eine Fehler zurueckgibt,
anstatt den Zustand des Objektes zu aendern, falls die gespeichter
Thread-Id nicht mit der aktuellen Thread-ID uebereinstimmt.

Die Loesung fuer diese Problem ist dafuer zu sorgen, dass sich alle
relevanten Bibliotheksobjekte in einem 'geeigneten' Zustand befinden,
bevor ein Fork-Aufruf erfolgt.

> Der Kindprozess k�nnte also, hinreichend br�sige Bibliothek voraus-
> gesetzt, an der "}" nach dem fork() h�ngen bleiben beim Wegr�umen
> irgendeines C++-Objekts.

'Hinreichend braesige Bibliotheken vorrrausgesetzt' koennten 'beim
Wegraeumen eines C++-Objektes' auch die ersten zwanzig Code-Bytes
einer zufaellig ausgewaehlten Unteroutine mit Zufallszahlen
ueberschrieben werden. Das sind dann konkrete technische Probleme,
gegen die man konkret etwas tun kann (zB koennte man annehmen, dass
'C++Bibliothek' und 'hinreichende braesig' synonym sind und den Code
in einem Quarantaene-Prozess isolieren, der mit dem eigentlichen
Programm nur via IPC interagiert :-).

> Grund genug, es f�r "nicht funktionierend" zu halten.

Allerdings sind das alles 'dumme Dinge', die 'die pthread-Leute' ohne
Not in eine Spezifikation geschrieben haben, die mit C++ nichts zu tun
hat.

[*] Das ist ein ziemlich billiger sophistischer Trick: Man mache eine
inhaltsfreie Aussage die mit ein paar 'Fangbegriffen' garniert
ist. Dadurch veranlasst man, naive Mitglieder des Publikums auf der
Basis ihres eigenen besseren Wissens einen moeglichen Sinn zu
erfinden. Danach haben sie das Gefuehl, dem Vorredner zugestimmt zu
haben, obwohl sie eigentlich sich selber zustimmen.


Edzard Egberts

unread,
May 3, 2013, 3:20:25 PM5/3/13
to
Stefan Reuther schrieb:
> Rainer Weikusat wrote:
>> Gerald Breuer <Gerald...@googlemail.com> writes:
>>> Also C++ hat mittlerweie Threads, und wenn ich da Mutexe oder Condi-
>>> tion-Variablen nutze die z.T. auf Kernel-Resourcen aufbauen die beim
>>> erstellen des neuen Prozesses nicht dupliziert werden wird's Probleme
>>> geben.

Ups, sollte ich mal wieder iso-c++ abonnieren? Seit wann hat C++ Threads
und Mutexe? Ich kenne das nur als Funktionen von Operationssystemen,
nicht als Bestandteil der Programmiersprache.

> Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
> und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
> die in einem C++-Programm gerne mal implizit benutzt werden, sind da
> nicht darunter.

malloc/free ist C, als C++ nennt sich das new/delete. Fork() impliziert
also Probleme der Speicherverwaltung - geh�ren mit malloc oder new
allozierte Speicherbereiche zu den nicht duplizierten Ressourcen? Der
Heap geh�rt doch zum Prozess?

> Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
> Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
> sind: falls den ein anderer Thread gerade hat, kann man nur verlieren.
> Der Kindprozess k�nnte also, hinreichend br�sige Bibliothek voraus-
> gesetzt, an der "}" nach dem fork() h�ngen bleiben beim Wegr�umen
> irgendeines C++-Objekts. Grund genug, es f�r "nicht funktionierend" zu
> halten.

Um was f�r ein Objekt k�nnte es sich da handeln? Ein Beispiel w�rde mir
sicher helfen, das besser zu verstehen.


Rainer Weikusat

unread,
May 3, 2013, 3:47:43 PM5/3/13
to
Edzard Egberts <ed...@tantec.de> writes:
> Stefan Reuther schrieb:

[...]

>> Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
>> und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
>> die in einem C++-Programm gerne mal implizit benutzt werden, sind da
>> nicht darunter.
>
> malloc/free ist C, als C++ nennt sich das new/delete. Fork()
> impliziert also Probleme der Speicherverwaltung -

Wenn ein Prozess multithreaded ist muss der mutmasslich gemeinsame
Heap 'irgendwie' mit locks gesichert werden und falls das
'pthread'-Mutex-Objekte sind, koennte ein solcher Mutex von einem
anderen thread als demjenigen, der fork ausfuehrt, gelock worden sein
und die pthread-Spezifiaktion fordert, das dieser Mutex im neuen
Prozess nicht mehr freigegeben werden kann.

Peter Kruse

unread,
May 3, 2013, 3:50:22 PM5/3/13
to
Am 03.05.2013 21:11, schrieb Rainer Weikusat:

> Wenn man sowohl 'C++' als auch 'Kernel-Resourcen' mal grosszuegig
> unter den Tisch fallen laessst bzw 'Kernel-Resourcen' inkorrekt
> als 'threads' interpretiert, ...

Ein Mutex oder eine Condition-Variable hat einen Userland-Teil
(beim Mutex ist es z.B. nur ein Z�hler) - �blichweise zumindest
damit im Fall einer Nicht-Contention das Locken, Signalisieren,
Sigalisiert bekommen oder Unlocken schneller geht - und einen
Kernel-Teil der genutz wird wenn ein Thread warten muss oder
ein wartender aufgeweckt werden muss. Diesen als Kernel-Resource
zu bezeichnen ist schon passend. Das ist prinzipiell sowohl f�r
die Posix-Funktionen als auch f�r die C++-Klassen das selbe.
Und da genau dieser Teil nicht bei fork() kopiert wird funktio-
niert eben das Kopieren von MT-Prozessen die Mutexe oder Monitore
einsetzen nicht.

> [*] Das ist ein ziemlich billiger sophistischer Trick: Man mache
> eine inhaltsfreie Aussage die mit ein paar 'Fangbegriffen' garniert
> ist. Dadurch veranlasst man, naive Mitglieder des Publikums auf der
> Basis ihres eigenen besseren Wissens einen moeglichen Sinn zu
> erfinden. Danach haben sie das Gefuehl, dem Vorredner zugestimmt
> zu haben, obwohl sie eigentlich sich selber zustimmen.

Und Du f�hlst dich offensichtlich durch das was die Autorit�t ande-
erer gegen�ber dir herabgesetzt. Ganz sch�n paranoid. Das ist ein
Charakterzug der mir bei dir ziemlich durchg�ngig auff�llt.

Peter Kruse

unread,
May 3, 2013, 3:53:35 PM5/3/13
to
Am 03.05.2013 21:50, schrieb Peter Kruse:

> Und Du f�hlst dich offensichtlich dadurch in deiner Autorit�t
> gegen�ber anderen herabgesetzt.



Gerald Breuer

unread,
May 3, 2013, 3:57:34 PM5/3/13
to
Am 03.05.2013 21:53, schrieb Peter Kruse:

>> Und Du f�hlst dich offensichtlich dadurch in deiner Autorit�t
>> gegen�ber anderen herabgesetzt.

ACK; der ist plemplem.


Rainer Weikusat

unread,
May 3, 2013, 3:57:41 PM5/3/13
to
Peter Kruse <Peter...@gmail.com> writes:
> Am 03.05.2013 21:11, schrieb Rainer Weikusat:
>
>> Wenn man sowohl 'C++' als auch 'Kernel-Resourcen' mal grosszuegig
>> unter den Tisch fallen laessst bzw 'Kernel-Resourcen' inkorrekt
>> als 'threads' interpretiert, ...
>
> Ein Mutex oder eine Condition-Variable hat einen Userland-Teil
> (beim Mutex ist es z.B. nur ein Z�hler) - �blichweise zumindest
> damit im Fall einer Nicht-Contention das Locken, Signalisieren,
> Sigalisiert bekommen oder Unlocken schneller geht - und einen
> Kernel-Teil der genutz wird wenn ein Thread warten muss oder
> ein wartender aufgeweckt werden muss. Diesen als Kernel-Resource
> zu bezeichnen ist schon passend.

[...]

> Und da genau dieser Teil nicht bei fork() kopiert wird funktioniert
> eben das Kopieren von MT-Prozessen die Mutexe oder Monitore
> einsetzen nicht.

Wie bereits aaO ausgefuehrt: Diese Aussage ist vollkommen falsch.

[...]

> Und Du f�hlst dich offensichtlich

Falls Du Dich so fuehlst, als ob dir 'das verborgene innere Wesen
andere' vollkommen 'offensichtlich' sei, solltest Du ein Jahrmarksbude
eroeffnen oder eine Therapie machen.

Peter Kruse

unread,
May 3, 2013, 3:59:57 PM5/3/13
to
Am 03.05.2013 21:57, schrieb Rainer Weikusat:

> Wie bereits aaO ausgefuehrt: Diese Aussage ist vollkommen falsch.

Nein, sie begr�ndet exakt die technischen Hintergr�nde warum
MT-Prozesse nicht mit fork() funktionieren.


Rainer Weikusat

unread,
May 3, 2013, 6:13:16 PM5/3/13
to
Edzard Egberts <ed...@tantec.de> writes:

[...]

> malloc/free ist C, als C++ nennt sich das new/delete. Fork()
> impliziert also Probleme der Speicherverwaltung

Mal ein bisschen Hintergrund dazu (was ich mir im Laufe der Jahre
zusammengereimt und -gesammelt) habe: 'Fork' ist ein hochgradig
'politisiertes' Thema und es gibt da wenigstens folgende Fraktion
(nicht alle hier vertreten):

Der folgende Text ist nicht fuer Leute ohne Sinn fuer Humor geeignet.




- UNIX(*)-Traditionalisten (nenne ich die mal): Fork ist das
sinnvolle 'primitive' fuer Parallellverarbeitung weil jeder
einzelne Prozess ein sequentieller Prozess mit
deterministischem Verhalten bleibt. 'Threads' sind hingegen
neumodisches Teufelszeug von dem man um seine unsterbliche
Seele und geistige Gesundheit zu bewahren, unter allen
Umstaenden die Finger lassen sollte.

- "die pthread-Leute" (die diese Spezifikation erfunden
haben): Weil wir threads haben, die wunderbar und modern
sind, ist fork obsolet, und wir koennen seiner Beerdigung ein
bisschen nachhelfen, in dem wir einfach keine sinnvolle
Interaktion von fork und multi-threading definieren

- "die 'computerisierte Schreibmaschinen'-Fraktion": Als dem
Propheten David Cutler VMS im Traum erschien, hatte es kein
fork. Den genauen Grund dafuer wissen wir nicht und
ueberhaupt ist das nur eine sinnlose Komplikation auf dem
Weg, ein anderes Programm zu starten, es ist als extrem
'baeh' und voller 'geheimnisvoller drohender' Problem. Fuer
die juengeren Mitglieder sind vermutlich sowohl 'Dave Cutler'
als auch 'VMS' boehmische Doerfer, da langt 'Billy the Gates
hat nie draufgepinkelt', was Microsoft tut, ist wohlgetan
und alles andere eh bloss Mist.

- aeltere Java-Programmierer. 'Aelter' heisst hier 'sie
assozieren Java mit Sun-Hardware und Solaris. Solaris/ BSD
emulieren 'bestimmte Eigenschaften' des UNIX V7
Prozessmanagements via Software obwohl das auf einem
'virtual memory'-System nicht allzuviel Sinn hat weil
Marshall Kirk McKusick mal in einem Buch geschrieben hat das
gehoere sich so. Der Endeffekt ist, dass man 'typische JVM
Prozesse' auf 'typischen Solaris-Rechnern' nicht forken
kann, weil im ganzen Universum nicht soviel swap space
existiert, dass es zwei davon geben koennte, die allen
Speicher, den die JVM 'bestimmt demnaechst irgendwann' via
'garbage collection' wiederbenutzbar macht, gleichzeitig
verwenden.

Pragmatisch gesehen ist der erste Standpunkt beruecksichtigenswert,
der zweite ruehrend naiv, der dritte sinnfreies Geklaeffe und der
vierte ein Problem der Anbieter 'kaputter Muell-UNIXe' (FvL).

Edzard Egberts

unread,
May 4, 2013, 4:50:49 AM5/4/13
to
Rainer Weikusat schrieb:
> Edzard Egberts <ed...@tantec.de> writes:
>> Stefan Reuther schrieb:
>
Das kommt mir gar nicht so besonders undefiniert vor, beim forken m�ssen
Threads und Mutex-Objekte also besonders behandelt werden. Da habe ich
mir noch nie Gedanken dr�ber gemacht, weil ich wohl zur
"'computerisierte Schreibmaschinen'-Fraktion" geh�re und f�r mich
Rechner auf Maschinen zu laufen haben. ;o)

Ich habe fork() bisher so gesehen, dass ich ein neues Programm starten
kann, beginnend mit einem neuen Prozess, der dann wieder Threads
initialisiert. Das kann �ber Pipe noch gesteuert werden, f�ngt ansonsten
aber von Null an. Ich wei�, dass der Befehl viel m�chtiger ist, habe
aber noch nicht versucht, einen Prozess vollst�ndig zu kopieren.

Ein Thread ist toll, wenn man blockende Peripherie verwalten muss, oder
bestimmte Reaktionszeiten erreichen will (GUI) - bei begrenzten
Ressourcen. Weitere Threads oder gar Prozesse sind meistens unn�tig,
weil die Ressource nur einmal existiert.

Fork() scheint mir dagegen eher f�r gro�e Maschinen anwendbar, wo z.B.
Webschnittstellen auf einen anderen Port kopiert werden, oder massive
Parallelverarbeitung statt findet. Und f�r den Start anderer Software
nat�rlich, z.B. aus einem Men� oder per login.

Wann genau st��t man denn auf diese Problematik und wie l�sst sich das
l�sen? Wo wir mit C++ angefangen haben - da w�rde ich dem Mutex doch
beispielsweise einen Copy-Construktor spendieren, der eine neue Instanz
anlegt?

Stefan Reuther

unread,
May 4, 2013, 4:47:03 AM5/4/13
to
Rainer Weikusat wrote:
> Stefan Reuther <stefa...@arcor.de> writes:
[fork vs. multithreaded]
>>Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
>>und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
>>die in einem C++-Programm gerne mal implizit benutzt werden, sind da
>>nicht darunter.
>
> Das ist zum einen nicht richtig:
>
> A process shall be created with a single thread. If a
> multi-threaded process calls fork(), the new process shall
> contain a replica of the calling thread and its entire address
> space, possibly including the states of mutexes and other
> resources. Consequently, to avoid errors, the child process
> may only execute async-signal-safe operations until such time
> as one of the exec functions is called.

��h, da steht genau das, was ich schrieb. Der Prozess darf nur "async
signal safe" Operationen ausf�hren. Ja, da steht "to avoid errors",
nicht "otherwise, the behaviour is undefined", aber das kommt aufs
gleiche raus.

>>Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
>>Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
>>sind:
>
> Fork kann das ganz wunderbar. 'Das Problem' ist hier das Verhalten,
> dass die UNIX(*)-Norm fuer 'Mutex-Objekte' fordert, naemlich dass
> diese nur von dem thread, dem sie gehoeren, wieder freigegeben werden
> koennen. Wenigstens fuer Linux wird das von der C-Library dadurch
> sichergestellt, dass die Bibliotheksroutine eine Fehler zurueckgibt,
> anstatt den Zustand des Objektes zu aendern, falls die gespeichter
> Thread-Id nicht mit der aktuellen Thread-ID uebereinstimmt.

Richtig. Deswegen schrieb ich "noch brauchbar sind". Irgendwas irgendwie
klonen wird schon gehen. Nur kann der Kernel hier nur verlieren:
entweder er klont den Mutex im gesperrten Zustand, dann kann ihn niemand
jemals wieder freigeben. Oder er entsperrt ihn im Kindprozess, dann ist
aber die Datenstruktur, die er sch�tzen sollte, immer noch inkonsistent.

> Die Loesung fuer diese Problem ist dafuer zu sorgen, dass sich alle
> relevanten Bibliotheksobjekte in einem 'geeigneten' Zustand befinden,
> bevor ein Fork-Aufruf erfolgt.

Nicht nur die Bibliotheksobjekte, *alle* Objekte. OK, es gibt
pthread_atfork, das Problem ist prinzipiell l�sbar. Aber Spa� ist was
anderes.

>>Der Kindprozess k�nnte also, hinreichend br�sige Bibliothek voraus-
>>gesetzt, an der "}" nach dem fork() h�ngen bleiben beim Wegr�umen
>>irgendeines C++-Objekts.
>
> 'Hinreichend braesige Bibliotheken vorrrausgesetzt' koennten 'beim
> Wegraeumen eines C++-Objektes' auch die ersten zwanzig Code-Bytes
> einer zufaellig ausgewaehlten Unteroutine mit Zufallszahlen
> ueberschrieben werden. Das sind dann konkrete technische Probleme,
> gegen die man konkret etwas tun kann (zB koennte man annehmen, dass
> 'C++Bibliothek' und 'hinreichende braesig' synonym sind und den Code
> in einem Quarantaene-Prozess isolieren, der mit dem eigentlichen
> Programm nur via IPC interagiert :-).

Der Quarant�ne-Prozess zum Abforken von Kindprozessen ist im allgemeinen
eine gute Idee, wenn man multithreaded arbeitet. Ich mache das vor allem
deswegen, weil es quasi unm�glich ist, alle Filedeskriptoren wieder
einzufangen, die die Kindprozesse so erzeugen. Ein paar der freien Unixe
haben da zwar Erweiterungen nachgelegt, mit denen man Dateien von
vornherein mit FD_CLOEXEC �ffnen kann, aber das m�sste man jeder
verd***ten Bibliothek beibringen und w�rde dadurch zur Belohnung noch
unportabel. Portabel w�re, alle jemals ge�ffneten fds zu tracken, und
dann im Kindprozess
for (int i = 3; i <= max_fd_ever_seen + 2*num_threads; ++i)
close(i);
zu machen. Muss man ebenfalls allen Bibliotheken beibringen, furchtbar
ineffizient, und hilft nicht gegen Spa�v�gel, die in einem Thread
'dup2(0, 5555);' machen.


Stefan

Stefan Reuther

unread,
May 4, 2013, 4:57:45 AM5/4/13
to
Edzard Egberts wrote:
> Stefan Reuther schrieb:
>> Rainer Weikusat wrote:
>>> Gerald Breuer <Gerald...@googlemail.com> writes:
>>>> Also C++ hat mittlerweie Threads, und wenn ich da Mutexe oder Condi-
>>>> tion-Variablen nutze die z.T. auf Kernel-Resourcen aufbauen die beim
>>>> erstellen des neuen Prozesses nicht dupliziert werden wird's Probleme
>>>> geben.
>
> Ups, sollte ich mal wieder iso-c++ abonnieren? Seit wann hat C++ Threads
> und Mutexe? Ich kenne das nur als Funktionen von Operationssystemen,
> nicht als Bestandteil der Programmiersprache.

Seit C++11 gibt es Threads in der C++-Standardbibliothek. C11 bringt
ebenfalls eine Thread-Bibliothek mit. Die Thread-Bibliothek von Boost
war schon immer on-topic in der C++-Newsgroup. 'fork' allerdings nicht.

>> Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
>> und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
>> die in einem C++-Programm gerne mal implizit benutzt werden, sind da
>> nicht darunter.
>
> malloc/free ist C, als C++ nennt sich das new/delete. Fork() impliziert
> also Probleme der Speicherverwaltung - geh�ren mit malloc oder new
> allozierte Speicherbereiche zu den nicht duplizierten Ressourcen? Der
> Heap geh�rt doch zum Prozess?

Ein multithread-taugliches Speicherverwaltungspaket hat irgendwo einen
Mutex, der seinen internen Status sch�tzt. Wenn ein Thread gerade forkt,
w�hrend ein anderer gerade in malloc unterwegs ist, wird der gerade
inkonsistente Zustand des Heaps geforkt, und der Kindprozess wird nicht
in der Lage sein, seinen Heap zu verwenden. Entweder, weil der Mutex
immer noch gesperrt ist und er schlicht nicht rankommt, oder, weil der
Mutex nicht dupliziert/freigegeben wurde und der Heap-Zustand
inkonsisten ist.

POSIX/SUS stellt Mittel zur Verf�gung, das zu l�sen (pthread_atfork),
verlangt aber nicht von der Library, das zu tun.

>> Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
>> Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
>> sind: falls den ein anderer Thread gerade hat, kann man nur verlieren.
>> Der Kindprozess k�nnte also, hinreichend br�sige Bibliothek voraus-
>> gesetzt, an der "}" nach dem fork() h�ngen bleiben beim Wegr�umen
>> irgendeines C++-Objekts. Grund genug, es f�r "nicht funktionierend" zu
>> halten.
>
> Um was f�r ein Objekt k�nnte es sich da handeln? Ein Beispiel w�rde mir
> sicher helfen, das besser zu verstehen.

Zum Beispiel sowas:
----
int forkOrDie(std::string task) {
int result = fork();
if (result < 0) {
throw std::runtime_error("fork for " + task + " failed");
}
return result;
}
----
greift bei der R�ckkehr auf den Heap zu, um den Parameter wegzur�umen.


Stefan

Rainer Weikusat

unread,
May 4, 2013, 8:11:01 AM5/4/13
to
Stefan Reuther <stefa...@arcor.de> writes:
> Rainer Weikusat wrote:
>> Stefan Reuther <stefa...@arcor.de> writes:
> [fork vs. multithreaded]
>>>Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
>>>und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
>>>die in einem C++-Programm gerne mal implizit benutzt werden, sind da
>>>nicht darunter.
>>
>> Das ist zum einen nicht richtig:
>>
>> A process shall be created with a single thread. If a
>> multi-threaded process calls fork(), the new process shall
>> contain a replica of the calling thread and its entire address
>> space, possibly including the states of mutexes and other
>> resources. Consequently, to avoid errors, the child process
>> may only execute async-signal-safe operations until such time
>> as one of the exec functions is called.
>
> ��h, da steht genau das, was ich schrieb. Der Prozess darf nur "async
> signal safe" Operationen ausf�hren. Ja, da steht "to avoid errors",
> nicht "otherwise, the behaviour is undefined", aber das kommt aufs
> gleiche raus.

Zunaechst mal steht da 'if a multi-threaded process calls fork'. Nicht
jeder Prozess ist multi-threaded und die 'universelle Annahme' das zu
jedem Prozess irgendwelcher Code gehoert, von dem niemand weiss, was
er eigentlich genau tut, ist falsch: Das ist bloss der allgemeinste
denkbaren Fall, den diese Spezifiaktion abdecken muss.

Technisch gesehen sieht das so aus, das 'fork' sich zu anderen threads
genauso verhaelt, wie ein asynchron ausgefuehrter signal handler:
Diese werden zu einem beliebigen Zeitpunkt ohne Warnung und ohne die
Noeglichkeit, auf dieses Ereignis reagieren zu koennen,
unterbrochen. Je nachdem, was diese 'anderen threads' gerade am tun
waren, koennten sich also 'irgendwelche Datenstrukturen' im neuen
Prozess in einem 'inkorrekten' Zustand befinden und 'irgendwelcher
Code', der auf Annahmen ueber diese Datenstrukturen basiert, die in
Abwesenheit einer solchen 'asynchronen Unterbrechung' garantiert sind,
koennte deswegen 'unerwartetes Verhalten' an den Tag legen.

Etwas kuerzer koennte man diese Konjunktiv-Lawine als "Kraeht der Hahn
auf dem Mist, dann aendert sich's Wetter oder's bleibt wie's ist"
ausdruecken: Irgendetwas wird passieren. Leider haben wir keine Idee,
was genau, aber die Folgen werden furchtbar sein! Das ist kein
nuetzlicher Standpunkt fuer die Loesung technischer Probleme.

>>>Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
>>>Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
>>>sind:
>>
>> Fork kann das ganz wunderbar. 'Das Problem' ist hier das Verhalten,
>> dass die UNIX(*)-Norm fuer 'Mutex-Objekte' fordert, naemlich dass
>> diese nur von dem thread, dem sie gehoeren, wieder freigegeben werden
>> koennen. Wenigstens fuer Linux wird das von der C-Library dadurch
>> sichergestellt, dass die Bibliotheksroutine eine Fehler zurueckgibt,
>> anstatt den Zustand des Objektes zu aendern, falls die gespeichter
>> Thread-Id nicht mit der aktuellen Thread-ID uebereinstimmt.
>
> Richtig. Deswegen schrieb ich "noch brauchbar sind". Irgendwas irgendwie
> klonen wird schon gehen. Nur kann der Kernel hier nur verlieren:
> entweder er klont den Mutex im gesperrten Zustand, dann kann ihn niemand
> jemals wieder freigeben. Oder er entsperrt ihn im Kindprozess, dann ist
> aber die Datenstruktur, die er sch�tzen sollte, immer noch
> inkonsistent.

Der Kernel weiss davon gar nichts (oder sollte zumindestens nichts
davon wissen): Die pthread-Sychronisationsobjekte sind samt und
sonders dafuer gedacht, aus Performance-Gruenden soweit als moeglich
ohne Kernelbenutzung auszukommen. Andernfalls koennte man AF_UNIX
'datagram sockets' benutzen (damit kann Semaphore implementieren und
somit 'auch alles andere'). Das sind Probleme mancher Anwendungen, um
die sich diese Anwendungen selber kuemmern muessen oder muessten.

ZB kann ein geforkter Prozess, dessen Vaterprozess (klingt nicht
wirklich gut) zu einem Zeitpunkt fork aufgerufen hat, an dem alle
anderen threads entweder 'lockfrei' blockiert waren oder bei
Operationen unterbrochen wurden, die 'async signal safe' waren, alles
tun, was er moechte, ohne 'seltsame Effekte' zu erwarten zu
haben. Alternativ kann der thread, der fork aufruft, vorher alle
Mutexe sperren und nach dem fork wieder entsperren. Beides habe ich
schon benutzt. Ggf kuemmert sich auch die pthread-Implementierung gar
nicht um diese willkuerliche Einschraenkung (aka 'LinuxThreads') oder
es werden lock-Objekte benutzt, fuer die sie nicht gilt
(POSIX-Semaphore anstelle von Mutexen).

[...]

>> Die Loesung fuer diese Problem ist dafuer zu sorgen, dass sich alle
>> relevanten Bibliotheksobjekte in einem 'geeigneten' Zustand befinden,
>> bevor ein Fork-Aufruf erfolgt.
>
> Nicht nur die Bibliotheksobjekte, *alle* Objekte. OK, es gibt
> pthread_atfork, das Problem ist prinzipiell l�sbar. Aber Spa� ist was
> anderes.

pthread_atfork ist IIRC (zZt laeuft hier kein X, 'einfaches Suchen'
ist also nicht moeglich) selber nicht 'async signal safe' und somit
zur Loesung dieser Probleme aufgrund von historischen Defiziten in der
Spezifiaktion nicht geeignet.

>>>Der Kindprozess k�nnte also, hinreichend br�sige Bibliothek voraus-
>>>gesetzt, an der "}" nach dem fork() h�ngen bleiben beim Wegr�umen
>>>irgendeines C++-Objekts.
>>
>> 'Hinreichend braesige Bibliotheken vorrrausgesetzt' koennten 'beim
>> Wegraeumen eines C++-Objektes' auch die ersten zwanzig Code-Bytes
>> einer zufaellig ausgewaehlten Unteroutine mit Zufallszahlen
>> ueberschrieben werden. Das sind dann konkrete technische Probleme,
>> gegen die man konkret etwas tun kann (zB koennte man annehmen, dass
>> 'C++Bibliothek' und 'hinreichende braesig' synonym sind und den Code
>> in einem Quarantaene-Prozess isolieren, der mit dem eigentlichen
>> Programm nur via IPC interagiert :-).
>
> Der Quarant�ne-Prozess zum Abforken von Kindprozessen ist im allgemeinen
> eine gute Idee, wenn man multithreaded arbeitet.

Ich hatte allerdings schon einen (oder mehrere) Spezialprozesse zum
isolieren von 'flusigem Code'[*] gemeint: Was ich nicht ohne groessere
Schwierigkeiten aendern kann oder darf, fummelt mir nicht in MEINEM
Adressraum rum (soweit moeglich). Das bekommt seinen eigenen, wo es im
Zweifels mit einem Knueppel erschlagen (SIGKILL) und neugestartet
werden kann, ohne die 'Kernlogik' der Anwendung
durcheinanderzubringen. Damit kann man sich einen Haufen graue Haare
ersparen.

[*] ZB Bibliotheken, deren mitgelieferte Dokumentation sich
offensichtlich auf eine vollkommen andere Bibliothek mit aehnlicher
generaller Zielsetzung bezieht.

Rainer Weikusat

unread,
May 4, 2013, 8:51:34 AM5/4/13
to
Edzard Egberts <ed...@tantec.de> writes:
> Rainer Weikusat schrieb:
>> Edzard Egberts <ed...@tantec.de> writes:

[fork & threads]

> Ich habe fork() bisher so gesehen, dass ich ein neues Programm starten
> kann, beginnend mit einem neuen Prozess, der dann wieder Threads
> initialisiert. Das kann �ber Pipe noch gesteuert werden, f�ngt
> ansonsten aber von Null an. Ich wei�, dass der Befehl viel m�chtiger
> ist, habe aber noch nicht versucht, einen Prozess vollst�ndig zu
> kopieren.

Im Prinzip ist 'fork' ein Implementierungsdetail von PDP-8 UNIX(*):
Das hatte zwei Prozesse, naemlich einen fuer jedes Terminal, und keinen
'exec'-Systemaufruf, sondern der Code zum Starten eines neuen
Programmes war Bestandteil der shell. Dazu wollte jemand dann
'Hintergrundprozesse' hinzufuegen. Das wurde so implementiert, das der
Kernel einen der Shell-Prozesse kopierte und der bereits erwaehnte
existierende Code zum Starten eines neuen Programms im kopierten
Prozess weiterbenutzt wurde weil das Ken Thompson (IRRC) als die
einfachste Loesung erschien (Zusammenfassung aus dem Gedaecthnis,
Irrtum vorbehalten).

Davon abgesehen kann man es praktisch benutzen, wenn man mal grade
etwas bezogen auf den 'eigentlichen' Kontrollfluss asynchron erledigen
moechte. ZB eine Datei schreiben oder ein externes Kommando, das eine
gewisse Zeit braucht, ausfuehren, waehrend der 'eigentliche Prozess'
sich weiter um seine Dateibeschreiber kuemmern soll, wo 'Ereignisse'
stattfinden koennten, fuer deren Bearbeitung 'weiche
Echtzeitanforderungen' gelten. Oder falls man einen
Verarbeitungschritt unternehmen muss, der bekanntermassen zu einem
illegalen Speicherzugriff fuehren kann: In diesem Fall zerlegt es den
Kindprozess und der Elternprozess erhaelt eine 'das ging
schief'-Benachrichtung (benutzt habe ich das mal zum 'ueberpruefen',
ob man angebliche Bild-Dateien, die ein Benutzer via web interface
hochgeladen hatte, mit bestimmten Bibliotheksroutinen bearbeiten kann,
ohne den Versuch mit dem Leben (des Prozesses) zu bezahlen).

[...]

> Wann genau st��t man denn auf diese Problematik und wie l�sst sich das
> l�sen? Wo wir mit C++ angefangen haben - da w�rde ich dem Mutex doch
> beispielsweise einen Copy-Construktor spendieren, der eine neue
> Instanz anlegt?

Der Kopierkonstruktor wird aber nicht ausgefuehrt: Im Falle eines
forks macht der Kernel eine Speicher-zu-Speicher-Kopie von den
benutzen Teilen eines Prozess-Addressraums[*], erzeugt einen neuen
Prozess, dessen Addressraum die kopierten Daten enthaelt, und macht
dann in beiden Prozessen ein 'return to userspace' aus dem fork-Aufruf
heraus. Falls der Prozess single-threaded ist, ist das offensichtlich
kein Problem, weil alle 'Awendungsobjekte' sich in beiden Prozessen in
genau dem Zustand befinden, in dem sie sich vor dem fork befanden. Bei
Prozessen mit mehren threads werden die anderen threads asynchron zu
einem unvorhersehbaren Zeitpunkt angehalten, womit man sich im neuen
Prozess potentiell alle Schwierigkeiten einfaengt, mit denen ein
asynchron ausgefuehrt signal handler umgehen muss.

Wenn man das vermeiden moechte, muss man auf Anwendungsebene
sicherstellen, dass der fork zu einem Zeitpunkt ausgefuehrt wird, an
dem die Speicher-zu-Speicher-Kopie einen in sich konsisten
Schnappschuss machen wird. Theoretisch ist das nur dann moeglich, wenn
man allen Code, der im Addressraum der Anwendung ausgefuehrt wird,
auch tatsaechlich kontrollieren kann (in dem Sinne das man
'kooperatives Verhalten' erzwingen kann). Unter Beruecksichtigung der
zwei 'ueblichen, elastischen Annahmen', naemlich

a) ein grosser oder sogar der groesste Teil des
Anwendungscodes kommt aus Bibliotheken, deren
Implementierungsdetails weder dokumentiert noch (legal)
einsehbar sind

b) uebermorgen kommt ein (ex-)Student daher, der Blut und Wasser
schwitzt, wenn er Code schreiben muss, der die Summe der
Zahlen von 1 bis 9 berechnen soll, und dem alles egal ist ausser
diese Tatsache vor seinen Vorgesetzten zu verbergen

ist das Problem 'grundsaetzlich unloesbar'. Fuer jeden konkreten Fall
a) sollte sich allerdings ein Workaround finden lassen und die
b)-Faelle wandern 'langsam aber stetig' in der Vertrieb ab, wo sie von
Anfang an hinwollten (und gehoert haetten) :->.

[*] Konzeptuell. 'In Wirklichkeit' werden auf Systemen, die eine MMU
besitzen, die Seitenbeschreibertabellen so geaendert, das ein
Schreibzugriff von einem der beiden Prozesse einen page fault ausloest
und der Kernel kopiert Seite fuer Seite sobald das notwendig wird.

Stefan Reuther

unread,
May 5, 2013, 4:46:53 AM5/5/13
to
Rainer Weikusat wrote:
> Stefan Reuther <stefa...@arcor.de> writes:
>>>>Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
>>>>Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
>>>>sind:
>>>
>>>Fork kann das ganz wunderbar. 'Das Problem' ist hier das Verhalten,
>>>dass die UNIX(*)-Norm fuer 'Mutex-Objekte' fordert, naemlich dass
>>>diese nur von dem thread, dem sie gehoeren, wieder freigegeben werden
>>>koennen. Wenigstens fuer Linux wird das von der C-Library dadurch
>>>sichergestellt, dass die Bibliotheksroutine eine Fehler zurueckgibt,
>>>anstatt den Zustand des Objektes zu aendern, falls die gespeichter
>>>Thread-Id nicht mit der aktuellen Thread-ID uebereinstimmt.
>>
>>Richtig. Deswegen schrieb ich "noch brauchbar sind". Irgendwas irgendwie
>>klonen wird schon gehen. Nur kann der Kernel hier nur verlieren:
>>entweder er klont den Mutex im gesperrten Zustand, dann kann ihn niemand
>>jemals wieder freigeben. Oder er entsperrt ihn im Kindprozess, dann ist
>>aber die Datenstruktur, die er sch�tzen sollte, immer noch
>>inkonsistent.
> [...]
> ZB kann ein geforkter Prozess, dessen Vaterprozess (klingt nicht
> wirklich gut) zu einem Zeitpunkt fork aufgerufen hat, an dem alle
> anderen threads entweder 'lockfrei' blockiert waren oder bei
> Operationen unterbrochen wurden, die 'async signal safe' waren, alles
> tun, was er moechte, ohne 'seltsame Effekte' zu erwarten zu
> haben. Alternativ kann der thread, der fork aufruft, vorher alle
> Mutexe sperren und nach dem fork wieder entsperren. Beides habe ich
> schon benutzt. Ggf kuemmert sich auch die pthread-Implementierung gar
> nicht um diese willkuerliche Einschraenkung (aka 'LinuxThreads') oder
> es werden lock-Objekte benutzt, fuer die sie nicht gilt
> (POSIX-Semaphore anstelle von Mutexen).

Von den Semaphore-Funktionen ist auch nur sem_post "async signal safe".
Klar, das ist genau das, was man br�uchte, um einen kritischen Abschnitt
wiederzubekommen, der im gesperrten Zustand geklont wurde, hat aber
immer noch das Problem, dass man zum einen herausbekommen muss, ob man
das aktuell �berhaupt tun muss (stand ein anderer Thread im kritischen
Abschnitt?) und wie man die kaputte Datenstruktur reparieren muss. Alles
hinreichend unspa�ig.

>>>Die Loesung fuer diese Problem ist dafuer zu sorgen, dass sich alle
>>>relevanten Bibliotheksobjekte in einem 'geeigneten' Zustand befinden,
>>>bevor ein Fork-Aufruf erfolgt.
>>
>>Nicht nur die Bibliotheksobjekte, *alle* Objekte. OK, es gibt
>>pthread_atfork, das Problem ist prinzipiell l�sbar. Aber Spa� ist was
>>anderes.
>
> pthread_atfork ist IIRC (zZt laeuft hier kein X, 'einfaches Suchen'
> ist also nicht moeglich) selber nicht 'async signal safe' und somit
> zur Loesung dieser Probleme aufgrund von historischen Defiziten in der
> Spezifiaktion nicht geeignet.

pthread_atfork ruft man ja auch nicht nach dem fork auf, sondern davor,
und da packt man dann eben eine Funktion rein, die vor dem fork alle
Mutexe zieht und nachher wieder zur�ckbringt.


Stefan

Heinz-Mario Frühbeis

unread,
May 6, 2013, 6:40:37 AM5/6/13
to
Am 04.05.2013 10:57, schrieb Stefan Reuther:
> Edzard Egberts wrote:
>> Stefan Reuther schrieb:
>>> Rainer Weikusat wrote:
>>>> Gerald Breuer <Gerald...@googlemail.com> writes:
>>>>> Also C++ hat mittlerweie Threads, und wenn ich da Mutexe oder Condi-
>>>>> tion-Variablen nutze die z.T. auf Kernel-Resourcen aufbauen die beim
>>>>> erstellen des neuen Prozesses nicht dupliziert werden wird's Probleme
>>>>> geben.
>>
>> Ups, sollte ich mal wieder iso-c++ abonnieren? Seit wann hat C++ Threads
>> und Mutexe? Ich kenne das nur als Funktionen von Operationssystemen,
>> nicht als Bestandteil der Programmiersprache.
>
> Seit C++11 gibt es Threads in der C++-Standardbibliothek. C11 bringt
> ebenfalls eine Thread-Bibliothek mit. Die Thread-Bibliothek von Boost
> war schon immer on-topic in der C++-Newsgroup. 'fork' allerdings nicht.
>
>>> Und auch aktuelle Versionen von POSIX bzw. SUS erlauben zwischen fork()
>>> und exec() nur "async signal safe" Operationen. Dinge wie malloc/free,
>>> die in einem C++-Programm gerne mal implizit benutzt werden, sind da
>>> nicht darunter.
>>
>> malloc/free ist C, als C++ nennt sich das new/delete. Fork() impliziert
>> also Probleme der Speicherverwaltung - gehᅵren mit malloc oder new
>> allozierte Speicherbereiche zu den nicht duplizierten Ressourcen? Der
>> Heap gehᅵrt doch zum Prozess?
>
> Ein multithread-taugliches Speicherverwaltungspaket hat irgendwo einen
> Mutex, der seinen internen Status schᅵtzt. Wenn ein Thread gerade forkt,
> wᅵhrend ein anderer gerade in malloc unterwegs ist, wird der gerade
> inkonsistente Zustand des Heaps geforkt, und der Kindprozess wird nicht
> in der Lage sein, seinen Heap zu verwenden. Entweder, weil der Mutex
> immer noch gesperrt ist und er schlicht nicht rankommt, oder, weil der
> Mutex nicht dupliziert/freigegeben wurde und der Heap-Zustand
> inkonsisten ist.
>
> POSIX/SUS stellt Mittel zur Verfᅵgung, das zu lᅵsen (pthread_atfork),
> verlangt aber nicht von der Library, das zu tun.
>
>>> Und das ist genau das Problem: fork() kann eben Mutexe nicht auf eine
>>> Weise klonen, dass sie nach dem fork() im Kindprozess noch brauchbar
>>> sind: falls den ein anderer Thread gerade hat, kann man nur verlieren.
>>> Der Kindprozess kᅵnnte also, hinreichend brᅵsige Bibliothek voraus-
>>> gesetzt, an der "}" nach dem fork() hᅵngen bleiben beim Wegrᅵumen
>>> irgendeines C++-Objekts. Grund genug, es fᅵr "nicht funktionierend" zu
>>> halten.
>>
>> Um was fᅵr ein Objekt kᅵnnte es sich da handeln? Ein Beispiel wᅵrde mir
>> sicher helfen, das besser zu verstehen.
>
> Zum Beispiel sowas:
> ----
> int forkOrDie(std::string task) {
> int result = fork();
> if (result < 0) {
> throw std::runtime_error("fork for " + task + " failed");
> }
> return result;
> }
> ----
> greift bei der Rᅵckkehr auf den Heap zu, um den Parameter wegzurᅵumen.
>
>
> Stefan
>

Welche Mᅵglichkeiten gibt es mit C++ evtl noch um andere Programme aus
dem eigenen Programm heraus aufzurufen ohne das das eigene Programm
blockiert wird und das, wenn z. Bsp. ein aufgerufenes Programm mal
abstᅵrzt, nicht gleich alles mitgerissen wird?

Des weiteren, wie sieht das denn mit einer, oder mehreren Event-Queues
fᅵr ein GUI aus? Im Internet las ich, daᅵ es wohl per Threading nicht
funktioniert, aber wohl doch per fork()?
Und ich ᅵberlege, ob ich _eine Event-Queue setzen soll, oder ob man das
besser pro Prozess macht?

Fᅵr Hinweise und Tipps dankbar und
mit Gruᅵ
Heinz-Mario Frᅵhbeis

Edzard Egberts

unread,
May 7, 2013, 4:23:52 AM5/7/13
to
Heinz-Mario Frᅵhbeis schrieb:
> Welche Mᅵglichkeiten gibt es mit C++ evtl noch um andere Programme aus
> dem eigenen Programm heraus aufzurufen

AFAIK unter Linux/Unix nur noch den system-Befehl.

> Des weiteren, wie sieht das denn mit einer, oder mehreren Event-Queues
> fᅵr ein GUI aus?

Mit einer gut, mit mehreren ganz schlecht.

> Und ich ᅵberlege, ob ich _eine Event-Queue setzen soll, oder ob man das
> besser pro Prozess macht?

AFAIK gibt es pro Prozess eine Event-Queue, keine Ahnung, was Du da
setzen willst.

Rainer Weikusat

unread,
May 7, 2013, 6:31:31 AM5/7/13
to
Edzard Egberts <ed...@tantec.de> writes:
> Heinz-Mario Fr�hbeis schrieb:
>> Welche M�glichkeiten gibt es mit C++ evtl noch um andere Programme aus
>> dem eigenen Programm heraus aufzurufen
>
> AFAIK unter Linux/Unix nur noch den system-Befehl.

Im allgemeinen sollte man system vermeiden (ausser man ist primaer
daran interessiert, in minimalem Umnfang Entwicklungszeit zu
sparen). Das tut ungefaehr folgendes:

1. Es forkt den aufrufenen Prozess.
2. Es fuehrt via exec einen shell-Prozess aus, dem der das
'system'-Argument als Kommandozeile uebergeben wird.
3. Es wartet auf dessen Ende.

Der shell-Prozess selber (fuer ein simples Kommando)

1. Parser die uebergebene Kommandozeile.
2. Forkt.
3. Fuert das eigentliche Kommando via exec aus
4. Wartet auf dessen Ende

Man hat also doppelt soviele Prozesse erzeugt, wie notwendig, von
denen die meisten nichts tun ausser um 'system'-Interface
herumzuwuergen. Dabei kann erheblich mehr schiefgehn, als wenn man das
beabsichtige Kommando direkt ausfuehrt. Aber damit einen das nicht zu
sehr beunruhigt,

http://hitchhikers.wikia.com/wiki/Joo_Janta_200_Super-Chromatic_Peril_Sensitive_Sunglasses

bekommt man keine sinnvollen Fehlerinformation mehr.

Heinz-Mario Frühbeis

unread,
May 7, 2013, 6:52:06 AM5/7/13
to
Na ja, "setzen" ist vllt das falsche Wort.
Es ginge mir um XLib-Fenster, wo ja nach dem Erzeugen eines Fensters
eine Event-Queue codiert wird.

Und eine Event-Queue pro Prozess ist machbar, ja? Dann kᅵnnte ich also
bei fork() eine Klasse generieren, die dann wiederum das Programm aufruft.
Nur "beiᅵt" sich das wohl wieder, da es ja nach dem Programm-Start
"blockiert". Danach wᅵrde also soweit ich das verstanden habe niemals
die Event-Queue aufgerufen werden?
Oder ich generiere eine Klasse, aus der heraus ein Programm gestartet
wird. Dieses Programm ruft dann aus einem Shared Memory eine weitere
Klasse auf, die ein Fenster erzeugt und eine Event-Queue liefert?

Es ginge mir also darum, daᅵ ein aufgerufenes Programm auf eine
Event-Queue quasi zurᅵckgreifen kann.
Und z. Z. stelle ich mir das so vor:
Hauptprogramm wird gestartet >
es werden eine Registry eingelesen und das System wird eingerichtet und
ein Shared Memory eingerichtet aus dem heraus jedes Programm *seine
Objekte beziehen kann >
es wird eine "Base" per fork() geladen, die z. Bsp. 2 Fenster hat (z.
Bsp. eine Taskbar und ein Manager) >
aus dieser Base heraus kᅵnnen dann andere Programme (auch per fork)
gestartet werden
(Alle Programme sollen auf die systemeigenen Fenster, am Besten per
CallBack<?>, zurᅵckgreifen.)

Mit Gruᅵ
Heinz-Mario Frᅵhbeis

Edzard Egberts

unread,
May 7, 2013, 7:30:38 AM5/7/13
to
Heinz-Mario Frᅵhbeis schrieb:
> Am 07.05.2013 10:23, schrieb Edzard Egberts:
>> AFAIK gibt es pro Prozess eine Event-Queue, keine Ahnung, was Du da
>> setzen willst.
>
> Na ja, "setzen" ist vllt das falsche Wort.
> Es ginge mir um XLib-Fenster, wo ja nach dem Erzeugen eines Fensters
> eine Event-Queue codiert wird.

Ach ja, pro Fenster und nicht pro Prozess, da hast Du recht.

> Und eine Event-Queue pro Prozess ist machbar, ja?

Puh, da komme ich schwer ins Schleudern - unter Windows ging das schon,
dass ein Service Events abfragt (z.B. WM_ENDSESSION), fᅵr Daemons mᅵsste
das auch gehen, ich weiᅵ aber gerade nicht wie. Vielleicht ᅵber
signal-handler? Die Event-Queue wᅵre dann eine Eigenschaft des
XLib-Fensters, darᅵber hinaus kann ein Prozess Signale bearbeiten.

< snip >

Wie meinen?

> Und z. Z. stelle ich mir das so vor:
> Hauptprogramm wird gestartet >
> es werden eine Registry eingelesen und das System wird eingerichtet und
> ein Shared Memory eingerichtet aus dem heraus jedes Programm *seine
> Objekte beziehen kann >

Also eine Art Server, der Objekte zur Verfᅵgung stellt

> es wird eine "Base" per fork() geladen, die z. Bsp. 2 Fenster hat (z.
> Bsp. eine Taskbar und ein Manager) >

Das wᅵre dann ein unabhᅵngiger Client ("per fork() geladen" ist keine
sinnvolle Aussage) mit einem Fenster zur Anzeige der Objekte. "Taskbar"
und "Manager" sind wohl eher Widgets und keine Fenster. Es spricht aber
auch nichts dagegen, dass die "Base" Fenster ᅵffnet.

> (Alle Programme sollen auf die systemeigenen Fenster, am Besten per
> CallBack<?>, zurᅵckgreifen.)

Da bist Du vᅵllig auf dem Holzweg - Callback geht nicht
prozessᅵbergreifend, dafᅵr brauchst Du IPC (Inter Process
Communication), z.B. Sockets, Pipes oder den schon genannten Shared
Memory. Und Fenster wᅵrde ich auch eher als "prozesseigen" bezeichnen -
"systemeigen" sagt mir nichts.

Heinz-Mario Frühbeis

unread,
May 7, 2013, 8:01:38 AM5/7/13
to
Am 07.05.2013 13:30, schrieb Edzard Egberts:
> Heinz-Mario Frᅵhbeis schrieb:
>> Am 07.05.2013 10:23, schrieb Edzard Egberts:
>>> AFAIK gibt es pro Prozess eine Event-Queue, keine Ahnung, was Du da
>>> setzen willst.
>>
>> Na ja, "setzen" ist vllt das falsche Wort.
>> Es ginge mir um XLib-Fenster, wo ja nach dem Erzeugen eines Fensters
>> eine Event-Queue codiert wird.
>
> Ach ja, pro Fenster und nicht pro Prozess, da hast Du recht.

Habe ich? Mir fᅵllt gerade auf, daᅵ mehrere Fenster innerhalb eines
Prozesses nicht jeweils eine Event-Queue haben kᅵnnen.
Jedenfalls soweit ich das bisher hin bekommen habe.
Auch in allen mir bekannten Beispielen mit 'Multiple XLib Windows'
werden erst alle Fenster geladen und ganz zum Schluᅵ kommt die Event-Queue.
Einmal schrub jemand, daᅵ er es mit Multi-Threading versuchte, aber
nicht hin bekam.

>> Und eine Event-Queue pro Prozess ist machbar, ja?
>
> Puh, da komme ich schwer ins Schleudern - unter Windows ging das schon,
> dass ein Service Events abfragt (z.B. WM_ENDSESSION), fᅵr Daemons mᅵsste
> das auch gehen, ich weiᅵ aber gerade nicht wie. Vielleicht ᅵber
> signal-handler? Die Event-Queue wᅵre dann eine Eigenschaft des
> XLib-Fensters, darᅵber hinaus kann ein Prozess Signale bearbeiten.

Wenn ich mal davon ausgehe, daᅵ doch nur eine Event-Queue pro Prozess
geht, dann kann ein Fenster keine Eigenschaft "Event-Queue" haben.
Jedenfalls nicht direkt, da ja sonst jedes Fenster einen eigenen Prozess
brᅵuchte und das "macht man wohl eher nicht", oder? Jedenfalls konnte
ich das so nicht in der Systemᅵberwachung meiner LM14-KDE feststellen.
Da ist pro Programm ein Prozess.

Das mᅵᅵte dann "verkettet" werden. Evtl durch Shared Memory.

> < snip >
>
> Wie meinen?

Was meinen, wozu?

>> Und z. Z. stelle ich mir das so vor:
>> Hauptprogramm wird gestartet >
>> es werden eine Registry eingelesen und das System wird eingerichtet und
>> ein Shared Memory eingerichtet aus dem heraus jedes Programm *seine
>> Objekte beziehen kann >
>
> Also eine Art Server, der Objekte zur Verfᅵgung stellt

Kann man wohl so sagen.

>> es wird eine "Base" per fork() geladen, die z. Bsp. 2 Fenster hat (z.
>> Bsp. eine Taskbar und ein Manager) >
>
> Das wᅵre dann ein unabhᅵngiger Client ("per fork() geladen" ist keine
> sinnvolle Aussage) mit einem Fenster zur Anzeige der Objekte. "Taskbar"
> und "Manager" sind wohl eher Widgets und keine Fenster. Es spricht aber
> auch nichts dagegen, dass die "Base" Fenster ᅵffnet.

Na ja, ist denn nicht auch ein Widget ein Fenster? Und kann nicht aus
einem Fenster ein Widget werden, aber nicht umgekehrt?

>> (Alle Programme sollen auf die systemeigenen Fenster, am Besten per
>> CallBack<?>, zurᅵckgreifen.)
>
> Da bist Du vᅵllig auf dem Holzweg - Callback geht nicht
> prozessᅵbergreifend, dafᅵr brauchst Du IPC (Inter Process
> Communication), z.B. Sockets, Pipes oder den schon genannten Shared
> Memory. Und Fenster wᅵrde ich auch eher als "prozesseigen" bezeichnen -
> "systemeigen" sagt mir nichts.

Mit "systemeigen" meine ich, daᅵ einem externen Programm Fenster
bereitgestellt werden, die vom System verwaltet werden.
Angenommen ich bin schon in der "Base" und es existiert ein Programm XY.
In diesem Programm soll es dann eine Klasse geben, die mit meinem
Hauptprogramm kommunizieren kann, welche durch das Hauptprogramm
erstellt wurde.
Durch diese Klasse kann dann z. Bsp. ein Fenster erstellt werden.
Und durch die "Base" kann dann XY aufgerufen werden.
Damit wᅵre dann alles schᅵn beisam'.

Ich habe das unter Windows mit VB6 (quasi) genau so (per DLL's) gemacht.
Nur kann ich das _so nicht nach C++ "umstricken", da es (oder XLib) ja
"noch nicht einmal" einen Event-CallBack mitbringt.

Und da stellte sich mir eben die Frage: Mache ich _eine Event-Queue fᅵr
alles, oder eine pro Prozess. (Wobei mir gerade auffᅵllt, daᅵ ich evtl
Event-Loop meine... <duck?>.)
Mache ich das mit den Prozessen, dann brauche ich zusᅵtzlich zum
Event-Handling noch eine Prozessverwaltung...mache ich alles in einem
Prozess, dann darf gar nichts schief gehen, denn dann wᅵrde _alles
sofort geschossen werden.

Juergen Ilse

unread,
May 7, 2013, 8:37:48 AM5/7/13
to
Hallo,

Rainer Weikusat <rwei...@mssgmbh.com> wrote:
> naemlich als 'nicht definiert' und nicht, wie es der populaere
> Irrglaube moechte, als 'irgenetwas nicht vorhersagbares und total
> irrsinniges wird passieren' (das waere eine - wenn auch sehr vage -
> Definition).

"undefined behaviour" heisst, es ist nicht festgelegt was passiert,
es kann also durchaus irgend etwas nicht vorhersagbares und total
irrsinniges" passieren, aber ggfs. auch etwas sinnvolles oder gar
das, was man erwartet. Einer Implementierung steht es frei, das
Verhalten auch in den Faellen zu definieren, in denen der Standard
das nicht tut, nur kann man sich nicht darauf verlassen (solange
das nicht fuer diese konkrete Implementierung definiert ist).

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)
--
Ein Domainname ist nur ein Name, nicht mehr und nicht weniger.
Wer mehr hineininterpretiert, hat das Domain-Name-System nicht
verstanden.

Edzard Egberts

unread,
May 7, 2013, 8:59:29 AM5/7/13
to
Heinz-Mario Frᅵhbeis schrieb:
> Am 07.05.2013 13:30, schrieb Edzard Egberts:
>> Heinz-Mario Frᅵhbeis schrieb:
>>> Am 07.05.2013 10:23, schrieb Edzard Egberts:
>>>> AFAIK gibt es pro Prozess eine Event-Queue, keine Ahnung, was Du da
>>>> setzen willst.
>>> Es ginge mir um XLib-Fenster, wo ja nach dem Erzeugen eines Fensters
>>> eine Event-Queue codiert wird.
>> Ach ja, pro Fenster und nicht pro Prozess, da hast Du recht.
>
> Habe ich? Mir fᅵllt gerade auf, daᅵ mehrere Fenster innerhalb eines
> Prozesses nicht jeweils eine Event-Queue haben kᅵnnen.

Ich passe - mit so etwas musste ich mich seit Ewigkeiten nicht mehr
beschᅵftigen. Primᅵr gehen Events an Fenster(elemente), wie genau das
jetzt ablᅵuft, habe ich nicht parat. Vom Betriebssystem an die
Event-Loop des Prozesses und von da an die Fenster wᅵre eine Mᅵglichkeit.

> Wenn ich mal davon ausgehe, daᅵ doch nur eine Event-Queue pro Prozess
> geht, dann kann ein Fenster keine Eigenschaft "Event-Queue" haben.

Wie und woher auch immer, jedenfalls bekommt jedes Fenster die
betreffenden Events zugestellt.

> Jedenfalls nicht direkt, da ja sonst jedes Fenster einen eigenen Prozess
> brᅵuchte

Das sehe ich wiederum anders - ein Prozess kᅵnnte durchaus mehrere
Fenster mit eigenen Warteschlangen bearbeiten. Ich denke aber, dass
Fenster gar keinen Queue haben und der Prozess die Events direkt
zustellt, statt die pro Fenster zu puffern.

>> Wie meinen?
> Was meinen, wozu?

Den ganzen Abschnitt habe ich nicht kapiert.

> Mit "systemeigen" meine ich, daᅵ einem externen Programm Fenster
> bereitgestellt werden, die vom System verwaltet werden.

Komische Betrachtungsweise - fᅵr mich ᅵffnet ein Programm ein Fenster.
Dass das im Rahmen eines Betriebssystems passiert, interessiert mich
nicht weiter.

> Angenommen ich bin schon in der "Base" und es existiert ein Programm XY.
> In diesem Programm soll es dann eine Klasse geben, die mit meinem
> Hauptprogramm kommunizieren kann, welche durch das Hauptprogramm
> erstellt wurde.
> Durch diese Klasse kann dann z. Bsp. ein Fenster erstellt werden.
> Und durch die "Base" kann dann XY aufgerufen werden.

Ja und, wo ist das Problem?

> Nur kann ich das _so nicht nach C++ "umstricken", da es (oder XLib) ja
> "noch nicht einmal" einen Event-CallBack mitbringt.

Na ja, wenn ich mich recht entsinne, ist Dir mehrfach abgeraten worden,
die XLib zu verwenden. Da Du aber eben alles auf Low-Level-Basis selber
machen willst, musst Du Dir eben auch selber Deinen Event-Callback bauen.

> Mache ich das mit den Prozessen,

Also Aufteilung auf mehrere Programme.

> dann brauche ich zusᅵtzlich zum Event-Handling noch eine Prozessverwaltung.

Ja, wᅵre schon sinnvoll zu wissen, von welchem Programm ein Event kommt.

>..mache ich alles in einem
> Prozess, dann darf gar nichts schief gehen, denn dann wᅵrde _alles
> sofort geschossen werden.

Windows-Syndrom! Seit ich Open-Source-Toolkits nehme (ca. 10 Jahre),
stᅵrzen meine Programme nicht mehr ab, bzw. nur mit gutem Grund, der
sich finden und beheben lᅵsst. Ich lᅵse nur noch Probleme, die ich habe,
keine Probleme, die vielleicht auftauchen kᅵnnten.

Heinz-Mario Frühbeis

unread,
May 7, 2013, 9:44:00 AM5/7/13
to
Auch auf die Gefahr, daᅵ ich es noch nicht recht umschreiben kann:
Ich mᅵchte halt alle Programme im System miteinander kommunizieren
lassen und das geht AFAIK nur, wenn ich einen Sender habe und Empfᅵnger.
Dann kᅵnnte Programm X direkt mit Programm Y kommunizieren und das
System wᅵrde quasi nur dafᅵr gerade stehen, daᅵ beide ein Teil sind und
sofern natᅵrlich Programm Y das mᅵchte.

>> Angenommen ich bin schon in der "Base" und es existiert ein Programm XY.
>> In diesem Programm soll es dann eine Klasse geben, die mit meinem
>> Hauptprogramm kommunizieren kann, welche durch das Hauptprogramm
>> erstellt wurde.
>> Durch diese Klasse kann dann z. Bsp. ein Fenster erstellt werden.
>> Und durch die "Base" kann dann XY aufgerufen werden.
>
> Ja und, wo ist das Problem?
>
>> Nur kann ich das _so nicht nach C++ "umstricken", da es (oder XLib) ja
>> "noch nicht einmal" einen Event-CallBack mitbringt.
>
> Na ja, wenn ich mich recht entsinne, ist Dir mehrfach abgeraten worden,
> die XLib zu verwenden. Da Du aber eben alles auf Low-Level-Basis selber
> machen willst, musst Du Dir eben auch selber Deinen Event-Callback bauen.

... und ich habe noch rein gar keine Ahnung, wie ich diese Fenster
transparent kriegen soll. Und das werden sie sein...irgendwann.

>> Mache ich das mit den Prozessen,
>
> Also Aufteilung auf mehrere Programme.
>
>> dann brauche ich zusᅵtzlich zum Event-Handling noch eine
>> Prozessverwaltung.
>
> Ja, wᅵre schon sinnvoll zu wissen, von welchem Programm ein Event kommt.
>
>> ..mache ich alles in einem
>> Prozess, dann darf gar nichts schief gehen, denn dann wᅵrde _alles
>> sofort geschossen werden.
>
> Windows-Syndrom! Seit ich Open-Source-Toolkits nehme (ca. 10 Jahre),
> stᅵrzen meine Programme nicht mehr ab, bzw. nur mit gutem Grund, der
> sich finden und beheben lᅵsst. Ich lᅵse nur noch Probleme, die ich habe,
> keine Probleme, die vielleicht auftauchen kᅵnnten.

Nun ja, zumindest denke ich jetzt, daᅵ ich nicht ganz in die falsche
Richtung denke und kann zum nᅵchsten Problem: Boost::Shared Memory.

Danke fᅵrs Interesse!

Rainer Weikusat

unread,
May 7, 2013, 9:52:53 AM5/7/13
to
Juergen Ilse <jue...@usenet-verwaltung.de> writes:
> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>> naemlich als 'nicht definiert' und nicht, wie es der populaere
>> Irrglaube moechte, als 'irgenetwas nicht vorhersagbares und total
>> irrsinniges wird passieren' (das waere eine - wenn auch sehr vage -
>> Definition).
>
> "undefined behaviour" heisst, es ist nicht festgelegt was passiert,

In jedem gegebenen Kontext heisst es 'es wird nicht durch diesen Text
beschrieben'.

> es kann also durchaus irgend etwas nicht vorhersagbares und total
> irrsinniges" passieren,

Wenn dem so waere, stuende diese Tatsache nicht in Widerspruch zu dem
jeweils relevanten Dokument. Daraus folgt allerdings nicht, dass dem
so sein koennte: Um darueber Informationen zu bekommen, muesste
man sich woanders als in dem Text, der keine solchen enthaelt,
umsehen. Und die Vorstellungswelt von Leuten, die waehnen, ihnen
flatterten Daemon aus der Nase, ist meiner Ansicht nach kein
zuverlaessiges Nachschlagewerk fuer Informationen ueber das objektiv
beobachtbare Universum. Man koennte das den 'Unterschied zwischen
science und scientology' nennen :-).

Heinz-Mario Frühbeis

unread,
May 7, 2013, 10:13:03 AM5/7/13
to
Am 07.05.2013 15:52, schrieb Rainer Weikusat:
> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
>> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>>> naemlich als 'nicht definiert' und nicht, wie es der populaere
>>> Irrglaube moechte, als 'irgenetwas nicht vorhersagbares und total
>>> irrsinniges wird passieren' (das waere eine - wenn auch sehr vage -
>>> Definition).
>>
>> "undefined behaviour" heisst, es ist nicht festgelegt was passiert,
>
> In jedem gegebenen Kontext heisst es 'es wird nicht durch diesen Text
> beschrieben'.

Dem mᅵchte ich vom Inhalt zustimmen.
Software macht bis dato genau so, wie sie programmiert wurde und darum
ist sie auch nicht intelligent, auch nicht kᅵnstlich, oder auch "nur"
undefined. Das "kᅵnnte" sich mal ᅵndern, wenn vllt Software Software
programmiert..., oder so, aber wer will das schon.

Herbert Pophal

unread,
May 7, 2013, 11:04:58 AM5/7/13
to


On 05/07/2013 02:59 PM, Edzard Egberts wrote:
> Heinz-Mario Frᅵhbeis schrieb:
>> Am 07.05.2013 13:30, schrieb Edzard Egberts:
>>> Heinz-Mario Frᅵhbeis schrieb:
>>>> Am 07.05.2013 10:23, schrieb Edzard Egberts:
>>>>> AFAIK gibt es pro Prozess eine Event-Queue, keine Ahnung, was Du da
>>>>> setzen willst.
>>>> Es ginge mir um XLib-Fenster, wo ja nach dem Erzeugen eines Fensters
>>>> eine Event-Queue codiert wird.
>>> Ach ja, pro Fenster und nicht pro Prozess, da hast Du recht.
>>
>> Habe ich? Mir fᅵllt gerade auf, daᅵ mehrere Fenster innerhalb eines
>> Prozesses nicht jeweils eine Event-Queue haben kᅵnnen.
>
> Ich passe - mit so etwas musste ich mich seit Ewigkeiten nicht mehr
> beschᅵftigen. Primᅵr gehen Events an Fenster(elemente), wie genau das
> jetzt ablᅵuft, habe ich nicht parat. Vom Betriebssystem an die
> Event-Loop des Prozesses und von da an die Fenster wᅵre eine Mᅵglichkeit.

Ungefᅵhr so, ja. Es gibt genau eine event queue pro Prozess. Pro Fenster
ginge schon deswegen nicht, weil es X events gibt, die nichts mit
Fenstern zu tun haben.
In den ᅵblichen toolkits gibt es dann immer Funktionen/Methoden, die die
events an die widgets weitergeben, denen die Fenster zugeordnet sind.
Unverfensterte events sind natᅵrlich anders behandelt.
>
>> Wenn ich mal davon ausgehe, daᅵ doch nur eine Event-Queue pro Prozess
>> geht, dann kann ein Fenster keine Eigenschaft "Event-Queue" haben.

Ein Fenster gibt lediglich eine Liste von Events an, an denen es
"interessiert ist".

>
> Wie und woher auch immer, jedenfalls bekommt jedes Fenster die
> betreffenden Events zugestellt.
>
>> Jedenfalls nicht direkt, da ja sonst jedes Fenster einen eigenen Prozess
>> brᅵuchte
>
> Das sehe ich wiederum anders - ein Prozess kᅵnnte durchaus mehrere
> Fenster mit eigenen Warteschlangen bearbeiten. Ich denke aber, dass
> Fenster gar keinen Queue haben und der Prozess die Events direkt
> zustellt, statt die pro Fenster zu puffern.

Nicht auszuschlieᅵen, dass es toolkits gibt, die so etwas machen. Aber
nicht die Xlib.


Just my 2 ᅵ

Herbert

Juergen Ilse

unread,
May 7, 2013, 11:50:20 AM5/7/13
to
Hallo,

Heinz-Mario Frᅵhbeis <Earl...@web.de> wrote:
> Am 07.05.2013 15:52, schrieb Rainer Weikusat:
>> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
>>> "undefined behaviour" heisst, es ist nicht festgelegt was passiert,
>> In jedem gegebenen Kontext heisst es 'es wird nicht durch diesen Text
>> beschrieben'.

Korrekt. es ist noch nicht einmal garantiert, dass das Programm bei seiner
Ausfuehrung immer das gleiche oder auch nur annaehernd aehnliches tut ...
Man denke z.B. an das auslesen von uninitialisierten Speicher, dessen
Inhalt je nach genauem ystemzustand, Uhrzeit, Systemauslastung, ...
unterschiedlich sein kann. Das *koennte* (je nachdem, wie die gelesenen
Werte verwendet werden) jedes nur erdenkliche Softwareverhalten auf dem
System auf dem das Programm ausgefuehrt wird zur Folge haben. Wenn der
Rechner auf dem das Programm ausgefuehrt wird z.B. Verkehrsampeln
steuert, kann "undefiniertes Verhalten" in dem Fall Verkehrsunfaelle
zur Folge haben, steuert der Rechner auf dem das Programm ausgefuehrt
wird ein mit Atomraketen bestuecktes Raketensilo, koennte "undefined
behaviour" zum ausloesen eines Weltkriegs fuehren ...
Auch wenn so etwas eher Extremfaelle sind, die gern mal (nicht immer
ganz ernst gemeint) gelegentlich in dieser Gruppe angefuehrt werden,
sind sie dennoch denkbar, wenn sie "auf dem richtigen Rechner" aus-
gefuehrt werden ...

> Dem mᅵchte ich vom Inhalt zustimmen.
> Software macht bis dato genau so, wie sie programmiert wurde und darum
> ist sie auch nicht intelligent, auch nicht kᅵnstlich, oder auch "nur"
> undefined.

Auch heute kann man sich durchaus nicht darauf verlassen, dass "undefined
behaviour" wenigstens deterministisches Verhalten zur Folge haette, denn
in heutigen Systemen ist ist i.d.R. der Systemzustand bei mehrfacher
Programmausfuehrung nacheinander so gut wie niemals bei jedem Programm-
lauf gleich unter unguenstigen Umstaenden koennte so etwas dazu fuehren,
dass das Verhalten eines solchen Programms bei nahezu jedem Programmlauf
unterschiedlich sein koennte. Meiner Ansicht nach sollte man sich davor
hueten, bei undefiniertem Verhalten wenigstens von deterministischen
Verhalten auszugehen, denn u.U. ist dann noch nicht einmal das gegeben ...

Rainer Weikusat

unread,
May 7, 2013, 12:19:35 PM5/7/13
to
Juergen Ilse <jue...@usenet-verwaltung.de> writes:
> Heinz-Mario Fr�hbeis <Earl...@web.de> wrote:
>> Am 07.05.2013 15:52, schrieb Rainer Weikusat:
>>> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
>>>> "undefined behaviour" heisst, es ist nicht festgelegt was passiert,
>>> In jedem gegebenen Kontext heisst es 'es wird nicht durch diesen Text
>>> beschrieben'.
>
> Korrekt. es ist noch nicht einmal garantiert, dass das Programm bei seiner
> Ausfuehrung immer das gleiche oder auch nur annaehernd aehnliches
> tut ...

Ich koennte hier jetzt diese Beispiel demontieren, das ginge aber am
Kern der Sache genauso vorbei wie die 'redaktionelle Kuerzung' die Du
an meinem Text vorgenommen hast, an dessen Inhalt.

Rainer Weikusat

unread,
May 7, 2013, 12:29:38 PM5/7/13
to
Zusatzbemerkung: Hier wird ein logischer Fehler mit dem lateinischen
Namen 'Argumentum ad Ignorantiam' gemacht:

Wir wissen nicht, ob A falsch, also muss A wahr sein.

Die Abschwaechung zu

Wir wissen nicht, ob A falsch ist, also koennte A wahr sein.

aendert nichts am Kern des Folgerungsfehlers: 'Wir wissen es nicht'
bedeutet 'wir wissen es nicht' und nichts anderes: Daraus, das etwas
unbekannt ist, folgt nichts ueber diese etwas, die Aussage beschreibt
lediglich den Zustand desjenigen, auf den sie angwendet wird.

Stefan Reuther

unread,
May 7, 2013, 12:38:08 PM5/7/13
to
Rainer Weikusat wrote:
> Edzard Egberts <ed...@tantec.de> writes:
>>Heinz-Mario Fr�hbeis schrieb:
>>
>>>Welche M�glichkeiten gibt es mit C++ evtl noch um andere Programme aus
>>>dem eigenen Programm heraus aufzurufen
>>
>>AFAIK unter Linux/Unix nur noch den system-Befehl.
>
> Im allgemeinen sollte man system vermeiden (ausser man ist primaer
> daran interessiert, in minimalem Umnfang Entwicklungszeit zu
> sparen).

Wenn man dem Nutzer eine Schnittstelle "hier den Shellbefehl reinf�llen"
geben will, passt das schon. Da muss man nicht die Shell in wacklig und
subtil fehlerhaft nachprogrammieren.

> Das tut ungefaehr folgendes:
>
> 1. Es forkt den aufrufenen Prozess.
> 2. Es fuehrt via exec einen shell-Prozess aus, dem der das
> 'system'-Argument als Kommandozeile uebergeben wird.
> 3. Es wartet auf dessen Ende.

Das gilt f�r bestimmte Implementationen. Es ist dem Bibliotheks-
Implementierer erlaubt, zu optimieren. Zum Beispiel durch Verwendung von
nicht standardisierten Funktionen wie spawnp, was im Falle des
kanadischen Betriebssystems das fork() spart und damit auch in
multithreaded-Umgebungen funktioniert.

Und es gibt zumindest f�r nicht-Unixe Implementationen, die "einfache
F�lle" selbst �bernehmen (Kommandozeile in Worte spalten, exec). Wie
g�ngig das unter Unixen ist, entzieht sich meiner Kenntnis.

> Der shell-Prozess selber (fuer ein simples Kommando)
>
> 1. Parser die uebergebene Kommandozeile.
> 2. Forkt.
> 3. Fuert das eigentliche Kommando via exec aus
> 4. Wartet auf dessen Ende

Auch das gilt f�r bestimmte Implementationen. Ich h�tte erwartet, es sei
Stand der Technik, dass die Shell sich f�r den letzten bzw. einzigen
Befehl nicht forkt. So verh�lt sich zumindest die bash.

Damit ist das einzige, was man zahlt, das Laden des Shell-Prozesses. Und
daf�r bekommt man dann einen hoffentlich robusten, standardkonformen
Befehlszeilenparser.

Wenn man nat�rlich nur eine konstante Kommandozeile ausf�hren will, die
man direkt in einen Parametersatz f�r execvp packen kann, mag das
Overkill sein.


Stefan

Edzard Egberts

unread,
May 7, 2013, 2:17:55 PM5/7/13
to
Heinz-Mario Frᅵhbeis schrieb:
> Am 07.05.2013 14:59, schrieb Edzard Egberts:
> Auch auf die Gefahr, daᅵ ich es noch nicht recht umschreiben kann:
> Ich mᅵchte halt alle Programme im System miteinander kommunizieren
> lassen und das geht AFAIK nur, wenn ich einen Sender habe und Empfᅵnger.
> Dann kᅵnnte Programm X direkt mit Programm Y kommunizieren und das
> System wᅵrde quasi nur dafᅵr gerade stehen, daᅵ beide ein Teil sind und
> sofern natᅵrlich Programm Y das mᅵchte.

Genau so etwas habe ich ᅵbrigens schon gemacht - ein Serverprogramm, von
dem aus weitere Programme gestartet werden kᅵnnen:

http://www.tantec.de/de/software/doc/programm-_und_dateistruktur/index.html

Das verwendet Sockets und der Sinn der Sache war eine modulare,
netzwerkfᅵhige Software, die besonders einfach um kundenspezifische
Module erweitert werden kann. Dabei kᅵnnen nicht nur Server
untereinander kommunizieren, sondern eine Personenverwaltung kᅵnnte auch
irgendwo im Netzwerk gestartet werden und auf den Server verbinden.
Deshalb verwendet das auch kein Shared-Memory. Unter Linux lᅵuft das
auch, weil die GUI systemunabhᅵngig ist und sich so Sachen wie Sockets
leicht ᅵbersetzen lieᅵen - ᅵbrigens werden da die Module tatsᅵchlich
geforkt.

Davon laufen tᅵglich hunderte Instanzen, teilweise 24/7, das
funktioniert also wirklich.

> ... und ich habe noch rein gar keine Ahnung, wie ich diese Fenster
> transparent kriegen soll. Und das werden sie sein...irgendwann.

Die XLib alleine reicht da sicherlich nicht, sondern Du musst auch einen
geeigneten Fenstermanager verwenden. Ein einzelnes Fenster "weiss" ja
nicht, welche Fenster dahinter liegen. Fᅵr einen Transparenzeffekt muss
der Fenstermanager die Inhalte der dahinter liegenden Fenster abfragen,
zusammenrechnen (transparentes Fenster ᅵber transparentem Fenster?) und
dann an den entsprechenden Fensterbereich ᅵbergeben. Auf XLib-Ebene
wirst Du wahrscheinlich schon einen Alpha-Kanal beschreiben kᅵnnen, ob
der auch ausgewertet wird, ist eine ganz andere Frage.

Mal ganz davon abgesehen, dass ich persᅵnlich transparente Fenster fᅵr
reichlich sinnfrei halte - Fenster sind doch gerade dazu da, einen
Ausgabebereich zu definieren, der vom Hintergrund getrennt ist.

Rainer Weikusat

unread,
May 7, 2013, 2:59:11 PM5/7/13
to
Stefan Reuther <stefa...@arcor.de> writes:
> Rainer Weikusat wrote:
>> Edzard Egberts <ed...@tantec.de> writes:
>>>Heinz-Mario Fr锟絟beis schrieb:
>>>
>>>>Welche M锟絞lichkeiten gibt es mit C++ evtl noch um andere Programme aus
>>>>dem eigenen Programm heraus aufzurufen
>>>
>>>AFAIK unter Linux/Unix nur noch den system-Befehl.
>>
>> Im allgemeinen sollte man system vermeiden (ausser man ist primaer
>> daran interessiert, in minimalem Umnfang Entwicklungszeit zu
>> sparen).
>
> Wenn man dem Nutzer eine Schnittstelle "hier den Shellbefehl reinf锟絣len"
> geben will, passt das schon. Da muss man nicht die Shell in wacklig und
> subtil fehlerhaft nachprogrammieren.

In diesem Fall hat man immer noch eine sonderbare Programmstruktur:
Anstatt einfache tools in shell-Skripten zu kombinieren, ruft man aus
komplizierten Programmen heraus die Shell auf.

>> Das tut ungefaehr folgendes:
>>
>> 1. Es forkt den aufrufenen Prozess.
>> 2. Es fuehrt via exec einen shell-Prozess aus, dem der das
>> 'system'-Argument als Kommandozeile uebergeben wird.
>> 3. Es wartet auf dessen Ende.
>
> Das gilt f锟絩 bestimmte Implementationen. Es ist dem Bibliotheks-
> Implementierer erlaubt, zu optimieren. Zum Beispiel durch Verwendung von
> nicht standardisierten Funktionen wie spawnp, was im Falle des
> kanadischen Betriebssystems das fork() spart und damit auch in
> multithreaded-Umgebungen funktioniert.
>
> Und es gibt zumindest f锟絩 nicht-Unixe Implementationen, die "einfache
> F锟絣le" selbst 锟絙ernehmen (Kommandozeile in Worte spalten, exec). Wie
> g锟絥gig das unter Unixen ist, entzieht sich meiner Kenntnis.

Perl tut das zum Beispiel, zumindestens wenn es zu der Ansicht kommt,
dass die Shell nicht wirklich benoetigt wird. Allerdings ist die
Definition von system

If command is a null pointer, the system() function shall
determine whether the host environment has a command
processor. If command is not a null pointer, the system()
function shall pass the string pointed to by command to that
command processor to be executed in an implementation-defined
manner;

Fuer 'bestimmte Implementierungen' mag es hier mehr oder minder
sinnvolle Abkuerzungs-Implementierungen geben. Moeglichweise sind die
sogar dokumentiert, die Dokumentation ist korrekt (fuer perl eine
gewagte Annahme) und so eine bestimmte Implementierung in der
bestimmten Version, wo alles drei zutrifft, wird sogar benutzt. Dann
bleibt einem nur doch die spassige Aufgabe, einen String mit
geeignetem quoting zusammenzubauen, der tatsaechlich die intendierte
Aktion veranlasst. Wenigstens solange niemand 'verdeckt' einen
ssh-Aufruf macht, um das Kommando woanders ausfuehren zu lassen,
wodurch sich die Quoting-Regeln vollkommen aendern (bzw quoting
ueberhaupt nicht mehr moeglich ist --- ich habe mir nicht die Muehe
gemacht, diese Untiefe genau auszuloten, sondern sie bloss
umschifft). Als Lohn fuer diesen schoenen Zeitvertreib darf man dann
Code laufenlassen, der den String wieder auseinandernimmt und
hoffentlich die urspruenglichen Teile wieder rekonstruiert, ob im
Kontext des 'System-Kommandoprozessors du jour' oder einer 'wacklig
und subtil fehlerhaft nachprogrammierten' aka 'aus einem beliebigen
Befehlsprozessor herauskopierten' bibliotheks-spezifischen
Parsing-Routine.

Sinnvolle Fehlerinformationen bekommt man immer noch keine:

The following exit values shall be returned:

0
The script to be executed consisted solely of zero or more
blank lines or comments, or both.

1-125
A non-interactive shell detected an error other than
command_file not found, including but not limited to syntax,
redirection, or variable assignment errors.

127
A specified command_file could not be found by a
non-interactive shell.

Otherwise, the shell shall return the exit status of the last
command it invoked or attempted to invoke (see also the exit
utility in Special Built-In Utilities).

Juergen Ilse

unread,
May 7, 2013, 3:54:22 PM5/7/13
to
Hallo,

Rainer Weikusat <rwei...@mssgmbh.com> wrote:
> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
Du kannst auch dementieren, dass die Erde rund ist, nur aendert dass
an den Tatsachen rein gar nichts ...

Ich behaupte nicht, dass bei "undefiniertem Verhalten" immer auch
"nicht deterministisches Berhalten" des Orogtamms die Folge *ist*,
sondern lediglich, dass das der Fall sein *koennte*, und das ist
schlicht so und kann von dir schwerlich widerlegt werden.

Tschuess,
Juergen Ilse (jue...@usrnet-verwaltung.de)

Stefan Reuther

unread,
May 8, 2013, 5:33:05 AM5/8/13
to
Rainer Weikusat wrote:
> Stefan Reuther <stefa...@arcor.de> writes:
>>Rainer Weikusat wrote:
[system]
>>>Im allgemeinen sollte man system vermeiden (ausser man ist primaer
>>>daran interessiert, in minimalem Umnfang Entwicklungszeit zu
>>>sparen).
>>
>>Wenn man dem Nutzer eine Schnittstelle "hier den Shellbefehl reinf�llen"
>>geben will, passt das schon. Da muss man nicht die Shell in wacklig und
>>subtil fehlerhaft nachprogrammieren.
>
> In diesem Fall hat man immer noch eine sonderbare Programmstruktur:
> Anstatt einfache tools in shell-Skripten zu kombinieren, ruft man aus
> komplizierten Programmen heraus die Shell auf.

Solche seltsamen Programmen mit sonderbarer Programmstruktur sind zum
Beispiel 'make', 'less', alles was mailcap auswertet, und einige mehr.
So sonderbar scheint das also nicht zu sein.

>>>Das tut ungefaehr folgendes:
>>>
>>> 1. Es forkt den aufrufenen Prozess.
>>> 2. Es fuehrt via exec einen shell-Prozess aus, dem der das
>>> 'system'-Argument als Kommandozeile uebergeben wird.
>>> 3. Es wartet auf dessen Ende.
>>
>>Das gilt f�r bestimmte Implementationen. Es ist dem Bibliotheks-
>>Implementierer erlaubt, zu optimieren. Zum Beispiel durch Verwendung von
>>nicht standardisierten Funktionen wie spawnp, was im Falle des
>>kanadischen Betriebssystems das fork() spart und damit auch in
>>multithreaded-Umgebungen funktioniert.
>>
>>Und es gibt zumindest f�r nicht-Unixe Implementationen, die "einfache
>>F�lle" selbst �bernehmen (Kommandozeile in Worte spalten, exec). Wie
>>g�ngig das unter Unixen ist, entzieht sich meiner Kenntnis.
>
> Perl tut das zum Beispiel, zumindestens wenn es zu der Ansicht kommt,
> dass die Shell nicht wirklich benoetigt wird. Allerdings ist die
> Definition von system
>
> If command is a null pointer, the system() function shall
> determine whether the host environment has a command
> processor. If command is not a null pointer, the system()
> function shall pass the string pointed to by command to that
> command processor to be executed in an implementation-defined
> manner;
>
> Fuer 'bestimmte Implementierungen' mag es hier mehr oder minder
> sinnvolle Abkuerzungs-Implementierungen geben. Moeglichweise sind die
> sogar dokumentiert, die Dokumentation ist korrekt (fuer perl eine
> gewagte Annahme) und so eine bestimmte Implementierung in der
> bestimmten Version, wo alles drei zutrifft, wird sogar benutzt. Dann
> bleibt einem nur doch die spassige Aufgabe, einen String mit
> geeignetem quoting zusammenzubauen, der tatsaechlich die intendierte
> Aktion veranlasst.

Das ist die gleiche Aufgabe, vor der man steht, wenn man ein Terminal
mit dem Shellprompt vor sich hat.

Abgesehen davon ist Quoting f�r die Shell ja nun absolut simpel. Vor
alle Zeichen, die nicht A-Za-z0-9_ sind, einen \, fertig. Wir reden ja
hier nicht von cmd.exe.

> Sinnvolle Fehlerinformationen bekommt man immer noch keine:
>
> The following exit values shall be returned:
>
> 0
> The script to be executed consisted solely of zero or more
> blank lines or comments, or both.
>
> 1-125
> A non-interactive shell detected an error other than
> command_file not found, including but not limited to syntax,
> redirection, or variable assignment errors.
>
> 127
> A specified command_file could not be found by a
> non-interactive shell.
>
> Otherwise, the shell shall return the exit status of the last
> command it invoked or attempted to invoke (see also the exit
> utility in Special Built-In Utilities).

Wenn man sich nicht v�llig verrenkt, bekommt man aus dem eigenen
fork/exec auch nicht viel mehr Informationen raus.

Klar, theoretisch k�nnte man vor dem forken eine Pipe aufmachen, auf
FD_CLOEXEC setzen, und nach fehlgeschlagenem exec da eine Fehler-
beschreibung inkl. errno-Wert reinwerfen. Oder in einem Shared-Memory-
Segment ein paar letzte Worte hinterlassen. Praktisch habe ich hinter
einem fehlgeschlagenen exec nie was anderes als perror+exit gesehen, und
das gibt genauso so einen bl�den inband-signalisierten 8-bit-Wert an den
Aufrufer wie 'system'.


Stefan

Heinz-Mario Frühbeis

unread,
May 8, 2013, 7:04:37 AM5/8/13
to
Am 07.05.2013 20:17, schrieb Edzard Egberts:
> Heinz-Mario Frᅵhbeis schrieb:
>> Am 07.05.2013 14:59, schrieb Edzard Egberts:
>> Auch auf die Gefahr, daᅵ ich es noch nicht recht umschreiben kann:
>> Ich mᅵchte halt alle Programme im System miteinander kommunizieren
>> lassen und das geht AFAIK nur, wenn ich einen Sender habe und Empfᅵnger.
>> Dann kᅵnnte Programm X direkt mit Programm Y kommunizieren und das
>> System wᅵrde quasi nur dafᅵr gerade stehen, daᅵ beide ein Teil sind und
>> sofern natᅵrlich Programm Y das mᅵchte.
>
> Genau so etwas habe ich ᅵbrigens schon gemacht - ein Serverprogramm, von
> dem aus weitere Programme gestartet werden kᅵnnen:
>
> http://www.tantec.de/de/software/doc/programm-_und_dateistruktur/index.html

Das ist von dir?

> Das verwendet Sockets und der Sinn der Sache war eine modulare,
> netzwerkfᅵhige Software, die besonders einfach um kundenspezifische
> Module erweitert werden kann. Dabei kᅵnnen nicht nur Server
> untereinander kommunizieren, sondern eine Personenverwaltung kᅵnnte auch
> irgendwo im Netzwerk gestartet werden und auf den Server verbinden.
> Deshalb verwendet das auch kein Shared-Memory. Unter Linux lᅵuft das
> auch, weil die GUI systemunabhᅵngig ist und sich so Sachen wie Sockets
> leicht ᅵbersetzen lieᅵen - ᅵbrigens werden da die Module tatsᅵchlich
> geforkt.
>
> Davon laufen tᅵglich hunderte Instanzen, teilweise 24/7, das
> funktioniert also wirklich.

Ich will und kann mich im Moment nicht auf Shared Memory festlegen, da
ich ja die Unterschiede zu Pipe, oder Sockets nur annᅵhernd kenne.
Also da bin ich quasi noch auf der Suche, was meinem System da am Besten
dienlich ist. Ich mᅵchte da aber hier nochmal konkret anfragen...

>> ... und ich habe noch rein gar keine Ahnung, wie ich diese Fenster
>> transparent kriegen soll. Und das werden sie sein...irgendwann.
>
> Die XLib alleine reicht da sicherlich nicht, sondern Du musst auch einen
> geeigneten Fenstermanager verwenden. Ein einzelnes Fenster "weiss" ja
> nicht, welche Fenster dahinter liegen. Fᅵr einen Transparenzeffekt muss
> der Fenstermanager die Inhalte der dahinter liegenden Fenster abfragen,
> zusammenrechnen (transparentes Fenster ᅵber transparentem Fenster?) und
> dann an den entsprechenden Fensterbereich ᅵbergeben. Auf XLib-Ebene
> wirst Du wahrscheinlich schon einen Alpha-Kanal beschreiben kᅵnnen, ob
> der auch ausgewertet wird, ist eine ganz andere Frage.
>
> Mal ganz davon abgesehen, dass ich persᅵnlich transparente Fenster fᅵr
> reichlich sinnfrei halte - Fenster sind doch gerade dazu da, einen
> Ausgabebereich zu definieren, der vom Hintergrund getrennt ist.
>

Naja, den Fenstermanager habe ich ja quasi durch mein Hauptprogramm, was
ja alles kennt, was da im gesamten Programmablauf "kreucht und fleucht".
Per VB6 habe ich mal ein reines PictureBox-Programm geschrieben mit nur
AlphaBlend (also AFAIK eine Pseudo-Transparenz). Das geht auch...nur so
ab vllt 8 Fenstern (PictureBoxes) gleichzeitig, dann geht es doch schon
etwas in die Knie (bei einem 2 GHz-Dual-Prozessor vllt 'ne halbe Sekunde
zum Zeichnen), wenn man z. Bsp. ein Fenster nach vorne holt, oder wenn
man auf einem unteren Fenster hoovered. Filme, oder so was sind zudem
auch sehr schwierig flᅵssig zu implementieren.

Ich bin halt ein Grafik-Freak und mMn hat Transparenz durchaus Sinn.
Und hat mMn u.a. den Vorteil, daᅵ man nicht immer "umfokusieren" muss um
etwas zu lesen, was eigentlich komplett verdeckt ist.

Es ist halt ein "Spieᅵrutenlaufen" mit den Farben und vom Kontrast her
im Verhᅵltnis zur Opacity.
Aber mMn ist das Erscheinungsbild dann schᅵner, da sich Farben ja quasi
nochmal "mischen".
Mit "normaler" Schrift kommt man da mMn auch nicht sehr weit. Ich habe
z. Bsp. immer eine "Pseudo-3D-Schrift" (per API) generiert. Diese lᅵᅵt
sich erstaunlicherweise immer gut lesen. Auch bei einem LCD und aus
verschiedenen Blickwinkeln heraus.

Es ist natᅵrlich eine Umgewᅵhnung fᅵrs Auge...aber wenn man es einmal
"akzeptiert" hat, dann hat man mE keine Schwierigkeiten mehr "normal" zu
arbeiten.

Edzard Egberts

unread,
May 8, 2013, 7:18:42 AM5/8/13
to
Heinz-Mario Frᅵhbeis schrieb:
> Am 07.05.2013 20:17, schrieb Edzard Egberts:
>> Genau so etwas habe ich ᅵbrigens schon gemacht - ein Serverprogramm, von
>> dem aus weitere Programme gestartet werden kᅵnnen:
>>
>> http://www.tantec.de/de/software/doc/programm-_und_dateistruktur/index.html
>
> Das ist von dir?

Software, Hardware und Homepage, alles von mir! Bis 2009 gehᅵrte mir der
Laden zu 50%, ist dann aber in der Wirtschaftskrise Konkurs gegangen.
Mein Ex-Kompagnon fᅵhrt das zwar noch weiter, hat aber auch keine andere
Wahl (wer stellt schon einen gescheiterten Geschᅵftsfᅵhrer ein?) -
ansonsten sollte man IMHO tote Pferde einfach nicht mehr reiten.

>>> ... und ich habe noch rein gar keine Ahnung, wie ich diese Fenster
>>> transparent kriegen soll. Und das werden sie sein...irgendwann.
>>
>> Die XLib alleine reicht da sicherlich nicht, sondern Du musst auch einen
>> geeigneten Fenstermanager verwenden. Ein einzelnes Fenster "weiss" ja
>> nicht, welche Fenster dahinter liegen. Fᅵr einen Transparenzeffekt muss
>> der Fenstermanager die Inhalte der dahinter liegenden Fenster abfragen,

> Naja, den Fenstermanager habe ich ja quasi durch mein Hauptprogramm, was
> ja alles kennt, was da im gesamten Programmablauf "kreucht und fleucht".

Also willst Du nur innerhalb Deines Programms Sachen zusammenfᅵgen? So
wie bei meiner Kundenoberflᅵche, wo freigestellte Sonnenbᅵnke in den
Hintergrund kopiert werden? Das ist natᅵrlich ein ganzes Ende einfacher.

> Und hat mMn u.a. den Vorteil, daᅵ man nicht immer "umfokusieren" muss um
> etwas zu lesen, was eigentlich komplett verdeckt ist.

Na ja, mich macht so ein Durcheinander eher dᅵsig, lenkt zu sehr ab -
ein Fokus reicht mir, sonst fange ich noch an zu schielen. ;o)

Rainer Weikusat

unread,
May 8, 2013, 9:17:15 AM5/8/13
to
Juergen Ilse <jue...@usenet-verwaltung.de> writes:
> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
>>> Heinz-Mario Fr�hbeis <Earl...@web.de> wrote:
>>>> Am 07.05.2013 15:52, schrieb Rainer Weikusat:
>>>>> Juergen Ilse <jue...@usenet-verwaltung.de> writes:
>>>>>> "undefined behaviour" heisst, es ist nicht festgelegt was passiert,
>>>>> In jedem gegebenen Kontext heisst es 'es wird nicht durch diesen Text
>>>>> beschrieben'.
>>> Korrekt. es ist noch nicht einmal garantiert, dass das Programm bei seiner
>>> Ausfuehrung immer das gleiche oder auch nur annaehernd aehnliches
>>> tut ...
>> Ich koennte hier jetzt diese Beispiel demontieren, das ginge aber am
>> Kern der Sache genauso vorbei wie die 'redaktionelle Kuerzung' die Du
>> an meinem Text vorgenommen hast, an dessen Inhalt.
>
> Du kannst auch dementieren, dass die Erde rund ist, nur aendert dass
> an den Tatsachen rein gar nichts ...


... allerdings bin ich hier der jeniger der auf der Basis von
beobachtbaren Fakten argumentiert (wie zB, dass die Erde rund ist),
waehrend Du die Abwesenheit von konkreten Information als
Rechtfertigung fuer beliebige (und ggf auch offensichtlich unsinnige)
Spekulationen zu verkaufen versuchst.

ZB laesst sich durch Beobachtung der 'Ereignisse', die auch einem
gegebenen Computersystem stattfinden, exakt vorhersagen, welcher Wert
an jeder addressierbaren 'Speicherstelle' zu jedem Zeitpunkt
gespeichert sein wird (solange man Fehlfunktionen der Hardware
unbetrachtet laesst -- sonst koennte man die Dinger naemlich gar nicht
programmieren) und tatsaechlich laesst sich das sogar aus dem Code
alleine schliessen. Fuer ein komplexes Programm ist dieses Problem
unter Umstaenden nicht trivial zu loesen, aber das ist dann wieder ein
Fall von 'ist mir unbekannt' und keiner von 'kann nicht in Erfahrung
gebracht werden'.

> Ich behaupte nicht, dass bei "undefiniertem Verhalten" immer auch
> "nicht deterministisches Berhalten" des Orogtamms die Folge *ist*,
> sondern lediglich, dass das der Fall sein *koennte*, und das ist
> schlicht so und kann von dir schwerlich widerlegt werden.

Soweit mir das bekannt ist, ist das Verhalten von 'Orogtammen'
ueberhaup undefiniert, einschliesslich der Frage, ob es ein solches
Verhalten ueberhaupt gibt :-> [SCNR].

Ob das der Fall sein koennte, haengt nicht davon ab, dass Du nicht
weisst, ob es der Fall sein koennte. Aus dem Nicht-Wissen 'folgt'
quasi, 'das es der Fall sein koennte oder auch nicht' was bloss eine
komplizierte Formulierung fuer 'keine Ahnung' ist.

Rainer Weikusat

unread,
May 8, 2013, 12:34:34 PM5/8/13
to
Stefan Reuther <stefa...@arcor.de> writes:
> Rainer Weikusat wrote:
>> Stefan Reuther <stefa...@arcor.de> writes:
>>>Rainer Weikusat wrote:
> [system]
>>>>Im allgemeinen sollte man system vermeiden (ausser man ist primaer
>>>>daran interessiert, in minimalem Umnfang Entwicklungszeit zu
>>>>sparen).
>>>
>>>Wenn man dem Nutzer eine Schnittstelle "hier den Shellbefehl reinf�llen"
>>>geben will, passt das schon. Da muss man nicht die Shell in wacklig und
>>>subtil fehlerhaft nachprogrammieren.
>>
>> In diesem Fall hat man immer noch eine sonderbare Programmstruktur:
>> Anstatt einfache tools in shell-Skripten zu kombinieren, ruft man aus
>> komplizierten Programmen heraus die Shell auf.
>
> Solche seltsamen Programmen mit sonderbarer Programmstruktur sind zum
> Beispiel 'make', 'less', alles was mailcap auswertet, und einige mehr.
> So sonderbar scheint das also nicht zu sein.

Die Aufgabe von make ist es, basierend auf deklarierten
Abhaengigkeiten und Datei-Zeitstempeln, bestimmte Sequenzen von
Shell-Kommandos auszufuehren. Diverse interaktive Programme bieten
einem Benutzer die Moeglichkeit, Shell-Kommandos
auszufuehren. 'mailcap' ist eine Sammlung von 'inline' Shellskripten,
die 'etwas sinnvolles' mit Dateien bestimmter Typen tun sollen. In
allen diesen Faellen werden nicht ein bestimmtes Kommando ausgefuehrt
um einen bestimmten Zweck zu erzielen (zB eine bestimmte Modifikation
der Routing-Tabelle oder des momentanen Paketfilter-Regelsatzes)
sondern 'fuehre ein beliebiges Shell-Kommando aus ist genau die
angestrebte Funktionalitaet. Insofern hatte ich Dich hier
missverstanden.

Wenigstens fuer mich ist 'der Normallfall' allerdings ein
nicht-interaktives Programm das 'der Einfachheit halber' fuer
bestimmte Aufgaben ein existierendes Programm, dass um das
entsprechende System-API drumherum gebaut wurde, ausfuehrt. ZB

ip addr add 10.1.2.254/24 dev eth0

um auf einem Linux-system eine zusaetzliche IPv4-Addresse an ein
Interface zu binden. Das ist eine Folge von Strings, die man so an
eine 'exec'-Funktion uebergeben kann.

[...]

>> Fuer 'bestimmte Implementierungen' mag es hier mehr oder minder
>> sinnvolle Abkuerzungs-Implementierungen geben. Moeglichweise sind die
>> sogar dokumentiert, die Dokumentation ist korrekt (fuer perl eine
>> gewagte Annahme) und so eine bestimmte Implementierung in der
>> bestimmten Version, wo alles drei zutrifft, wird sogar benutzt. Dann
>> bleibt einem nur doch die spassige Aufgabe, einen String mit
>> geeignetem quoting zusammenzubauen, der tatsaechlich die intendierte
>> Aktion veranlasst.
>
> Das ist die gleiche Aufgabe, vor der man steht, wenn man ein Terminal
> mit dem Shellprompt vor sich hat.

Allerdings kann man dann eine intelligente Entscheidung unter
Beruecksichtigung der tatsaechlichen Eingabedaten treffen.

> Abgesehen davon ist Quoting f�r die Shell ja nun absolut simpel. Vor
> alle Zeichen, die nicht A-Za-z0-9_ sind, einen \, fertig. Wir reden ja
> hier nicht von cmd.exe.

Fuer 'mailcap' wuerdest Du damit schon auf die Nase fallen:

[rw@sapphire]/tmp $eval `printf "echo '%s'\n" ab`
ab
[rw@sapphire]/tmp $eval `printf "echo '%s'\n" "a'b"`
bash: unexpected EOF while looking for matching `''
bash: syntax error: unexpected end of file
[rw@sapphire]/tmp $eval `printf "echo '%s'\n" "a\'b"`
bash: unexpected EOF while looking for matching `''
bash: syntax error: unexpected end of file
[rw@sapphire]/tmp $eval `printf "echo '%s'\n" "a'\''b"`
a'b

Es gibt da noch erheblich mehr Sonderfaelle. Das ist nur einer der mir
'zufaellig' bekannt ist. Man ist generall gut beraten, keine
'Kommandozeilen' irgendeiner Coleur via Textinterpolation
zusammenzubauen, wenn man auch die Moeglichkeit hat, die Daten
'explizit strukturiert' zu uebergeben.

>> Sinnvolle Fehlerinformationen bekommt man immer noch keine:
>>
>> The following exit values shall be returned:
>>
>> 0
>> The script to be executed consisted solely of zero or more
>> blank lines or comments, or both.
>>
>> 1-125
>> A non-interactive shell detected an error other than
>> command_file not found, including but not limited to syntax,
>> redirection, or variable assignment errors.
>>
>> 127
>> A specified command_file could not be found by a
>> non-interactive shell.
>>
>> Otherwise, the shell shall return the exit status of the last
>> command it invoked or attempted to invoke (see also the exit
>> utility in Special Built-In Utilities).
>
> Wenn man sich nicht v�llig verrenkt, bekommt man aus dem eigenen
> fork/exec auch nicht viel mehr Informationen raus.

In jedem Fall bekommt man fuer fork und exec den Fehlercode, den der
entsprechende System-Aufruf fuer die gegebenen Argumente (exec)
zurueckgegeben hat und der wird auch tatsaechlich ausgefuehrt. ZB kann
ich hier die zwei folgenden Kommandos ausfuehren:

[rw@sapphire]/tmp $sh -c 'chdir / ls'
bin boot data dev emul etc home lib lib32 lib64 lost+found media mnt opt proc root sable-home sable-local sbin selinux srv sys sysdata tmp usr var

[rw@sapphire]/tmp $dash -c 'chdir / ls'
[rw@sapphire]/tmp $

'dash' ist die 'Debian Almquist shell' (forkt uebrigens auch fuer
genau ein Kommando), die auf einem Debian-System auch als /bin/sh, dh
als 'System-Kommandoprozessor' installiert sein koennte, was auch
'unterschwellig' empfohlen wird, weil sie keine 'bashisms' vertruege
und kleiner und schneller sei. 'chdir' ist hier ein von mir
implementiertes Kommando, das in ein bestimmtes Verzeichnis wechseln
soll und danach 'den Rest der Kommandozeile' via exec
ausfuehren. Problem dabei: (d)ash hat undokumentiertes builtin
diese Namens, dass identisch zu 'cd' ist.

Man kann ausserdem auch auf den das 'Lebensende' des erzeugen
Prozesses waren und bekommt dann einen Status-Code, der sich
tatsaechlich auf diesen bezieht und nicht moeglicherweise auf die
shell: Nehmen wir mal an, dass sei 'killed by signal 11'. Welcher der
beiden Prozesse war es denn nun?

Stefan Reuther

unread,
May 8, 2013, 2:07:04 PM5/8/13
to
Hallo,

Rainer Weikusat wrote:
[fork/exec vs. system usw.]
> Wenigstens fuer mich ist 'der Normallfall' allerdings ein
> nicht-interaktives Programm das 'der Einfachheit halber' fuer
> bestimmte Aufgaben ein existierendes Programm, dass um das
> entsprechende System-API drumherum gebaut wurde, ausfuehrt. ZB
>
> ip addr add 10.1.2.254/24 dev eth0
>
> um auf einem Linux-system eine zusaetzliche IPv4-Addresse an ein
> Interface zu binden. Das ist eine Folge von Strings, die man so an
> eine 'exec'-Funktion uebergeben kann.

Ja, w�rde ich auch so machen. Beziehungsweise die Frage stellen, warum
man den Systemaufruf nicht gleich direkt aufruft und somit NOCH bessere
Diagnosem�glichkeiten erh�lt. Zugegebenerma�en kenne ich mich mit Linux-
Netzwerkkonfigurations-APIs nicht aus, und wei� nicht wieviel h�sslicher
Boilerplate-Code das wird. Bei mir hei�t der Befehl meistens 'mount',
und da hab ich mir halt mal die Syscalls rausgesucht und nehm jetzt die.

Ein wenig bin ich allerdings schon gl�cklich dar�ber, dass der Kollege
die Syscalls noch nicht kennt und den Befehl mit 'system' aufruft, da
kann ich n�mlich die mir nicht genehmen Kommandos aus dem Binary
rauspatchen :->

>>Abgesehen davon ist Quoting f�r die Shell ja nun absolut simpel. Vor
>>alle Zeichen, die nicht A-Za-z0-9_ sind, einen \, fertig. Wir reden ja
>>hier nicht von cmd.exe.
>
> Fuer 'mailcap' wuerdest Du damit schon auf die Nase fallen:
>
> [rw@sapphire]/tmp $eval `printf "echo '%s'\n" ab`
> ab
> [rw@sapphire]/tmp $eval `printf "echo '%s'\n" "a'b"`
> bash: unexpected EOF while looking for matching `''
> bash: syntax error: unexpected end of file
> [rw@sapphire]/tmp $eval `printf "echo '%s'\n" "a\'b"`
> bash: unexpected EOF while looking for matching `''
> bash: syntax error: unexpected end of file
> [rw@sapphire]/tmp $eval `printf "echo '%s'\n" "a'\''b"`
> a'b
>
> Es gibt da noch erheblich mehr Sonderfaelle.

Ich wei� jetzt nicht, was genau du damit demonstrieren wolltest (au�er,
dass eval, printf und sh die verschiedensten Quotingmechanismen haben).
Wenn ich eine Shell-Kommandozeile habe, und da irgendwie ein Wort
unterbringen muss
befehl --option <hier_soll_das_wort_hin>
quote ich das Wort mit der oben genannten Regel.

OK, das versagt m�glicherweise bei Backticks, aber die sind so kaputt,
dass ich die schon komplett verdr�ngt habe.

Und dann gibt's nat�rlich immer noch die M�glichkeit, im C-Programm
putenv und in der Shell-Zeile "$foo" zu benutzen.

>>>Sinnvolle Fehlerinformationen bekommt man immer noch keine:
>>>
>>> The following exit values shall be returned:
>>>
>>> 0
>>> The script to be executed consisted solely of zero or more
>>> blank lines or comments, or both.
>>>
>>> 1-125
>>> A non-interactive shell detected an error other than
>>> command_file not found, including but not limited to syntax,
>>> redirection, or variable assignment errors.
>>>
>>> 127
>>> A specified command_file could not be found by a
>>> non-interactive shell.
>>>
>>> Otherwise, the shell shall return the exit status of the last
>>> command it invoked or attempted to invoke (see also the exit
>>> utility in Special Built-In Utilities).
>>
>>Wenn man sich nicht v�llig verrenkt, bekommt man aus dem eigenen
>>fork/exec auch nicht viel mehr Informationen raus.
>
> In jedem Fall bekommt man fuer fork und exec den Fehlercode, den der
> entsprechende System-Aufruf fuer die gegebenen Argumente (exec)
> zurueckgegeben hat

ja sch�n, und weiter? Der exec-Fehlercode bleibt typischerweise im
Kindprozess und wird von diesem normalerweise auch nur auf einen 8-bit
Exitcode abgebildet. Das meinte ich mit Verrenkungen. Ja, es ist
m�glich, den errno-Wert an den Elternprozess zu kommunizieren (Pipe oder
Shared Memory), aber keiner tut's.

> und der wird auch tatsaechlich ausgefuehrt. ZB kann
> ich hier die zwei folgenden Kommandos ausfuehren:
>
> [rw@sapphire]/tmp $sh -c 'chdir / ls'
> bin boot data dev emul etc home lib lib32 lib64 lost+found media mnt opt proc root sable-home sable-local sbin selinux srv sys sysdata tmp usr var
>
> [rw@sapphire]/tmp $dash -c 'chdir / ls'
> [rw@sapphire]/tmp $
>
> 'dash' ist die 'Debian Almquist shell' (forkt uebrigens auch fuer
> genau ein Kommando), die auf einem Debian-System auch als /bin/sh, dh
> als 'System-Kommandoprozessor' installiert sein koennte, was auch
> 'unterschwellig' empfohlen wird, weil sie keine 'bashisms' vertruege
> und kleiner und schneller sei. 'chdir' ist hier ein von mir
> implementiertes Kommando, das in ein bestimmtes Verzeichnis wechseln
> soll und danach 'den Rest der Kommandozeile' via exec
> ausfuehren. Problem dabei: (d)ash hat undokumentiertes builtin
> diese Namens, dass identisch zu 'cd' ist.

Das w�rde ich f�r eine Macke der Shell halten, und da d�rfte fast jede
Shell ein paar davon haben. Im Zweifelsfall versaut's das Startscript
des Nutzers.

> Man kann ausserdem auch auf den das 'Lebensende' des erzeugen
> Prozesses waren und bekommt dann einen Status-Code, der sich
> tatsaechlich auf diesen bezieht und nicht moeglicherweise auf die
> shell: Nehmen wir mal an, dass sei 'killed by signal 11'. Welcher der
> beiden Prozesse war es denn nun?

Ich tendiere zumindest dazu, der Shell erstmal kein Signal 11 zuzutrauen.

Zugegeben, bei den Kanadiern wei� ich inzwischen, dass da Systemprozesse
gerne mal wegrauchen. 'mount' zum Beispiel. Ein Grund mehr, die Syscalls
direkt zu benutzen :)


Stefan

Juergen Ilse

unread,
May 8, 2013, 3:00:55 PM5/8/13
to
Hallo,

Rainer Weikusat <rwei...@mssgmbh.com> wrote:
> ZB laesst sich durch Beobachtung der 'Ereignisse', die auch einem
> gegebenen Computersystem stattfinden, exakt vorhersagen, welcher Wert
> an jeder addressierbaren 'Speicherstelle' zu jedem Zeitpunkt
> gespeichert sein wird (solange man Fehlfunktionen der Hardware
> unbetrachtet laesst -- sonst koennte man die Dinger naemlich gar nicht
> programmieren) und tatsaechlich laesst sich das sogar aus dem Code
> alleine schliessen.

Wenn das so in jedem Fall zutreffen wuerde, waere die von openssl
verwendete Methode zur "Entropie-Gewinnung" ueberall disfunktional
und/oder die durchgefuehrte Aenderung der Debian-Maintainer am Code
haette niemals zum "Debian-Openssl-Debakel" gefuehrt ...
Du bist derjenige, der hier seine bisherigen Beobachtungen (IMHO
unzulaessigerweise) verallgemeinert und die Moeglichkeit jeden
anderen Verhaltens verneint.

>> Ich behaupte nicht, dass bei "undefiniertem Verhalten" immer auch
>> "nicht deterministisches Berhalten" des Orogtamms die Folge *ist*,
>> sondern lediglich, dass das der Fall sein *koennte*, und das ist
>> schlicht so und kann von dir schwerlich widerlegt werden.
> Soweit mir das bekannt ist, ist das Verhalten von 'Orogtammen'

Wenn die Argumente ausgehen, reitet man auf Tippfehlern herum?

> Ob das der Fall sein koennte, haengt nicht davon ab, dass Du nicht
> weisst, ob es der Fall sein koennte. Aus dem Nicht-Wissen 'folgt'
> quasi, 'das es der Fall sein koennte oder auch nicht' was bloss eine
> komplizierte Formulierung fuer 'keine Ahnung' ist.

Korrekt. Insbesondere weiss ich aber nicht, dass es dann kein
"nicht deterministisches Verhalten der Software" geben koennte.
Ich kann also nicht guten Gewissens diese Moeglichkeit vermeinen,
was du aber zu tun scheinst. Fuer mich ist hiermit EOD.

Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)

Rainer Weikusat

unread,
May 8, 2013, 3:32:48 PM5/8/13
to
Juergen Ilse <jue...@usenet-verwaltung.de> writes:
> Rainer Weikusat <rwei...@mssgmbh.com> wrote:
>> ZB laesst sich durch Beobachtung der 'Ereignisse', die auch einem
>> gegebenen Computersystem stattfinden, exakt vorhersagen, welcher Wert
>> an jeder addressierbaren 'Speicherstelle' zu jedem Zeitpunkt
>> gespeichert sein wird (solange man Fehlfunktionen der Hardware
>> unbetrachtet laesst -- sonst koennte man die Dinger naemlich gar nicht
>> programmieren) und tatsaechlich laesst sich das sogar aus dem Code
>> alleine schliessen.
>
> Wenn das so in jedem Fall zutreffen wuerde, waere die von openssl
> verwendete Methode zur "Entropie-Gewinnung" ueberall disfunktional
> und/oder die durchgefuehrte Aenderung der Debian-Maintainer am Code
> haette niemals zum "Debian-Openssl-Debakel" gefuehrt ...

'Die OpenSSL-Method zur Entropiegewinnung' basiert darauf, Daten von
/dev/random oder aus einem 'random number file' zum Entropiepool
hinzuzufuegen. Unter bestimmten Umstaenden wird dabei der Inhalt von
nicht explizit initialisiertem Stackspeicher in den Pool gemixt 'weil
das jedenfalls nicht schadet'. Allerdings wird immer nur der
tatsaechlich mit 'Zufallsdaten' initialisierte Teil dieses Puffers als
'entropy that was added' vermerkt. Eine detailliertere Beschreibung
der Method und dieses Vorfalls findet man hier:

http://research.swtch.com/openssl

Das eignet sich natuerlich ueberhaupt nicht zur Stuetzung der
'interessanten' Behauptung das 'normale Speicherinhalte' sich anders
als aufgrund von 'CPU-Operationen', deren Effekt vorhersagbar sind,
aendern wuerden. Allerdings erfordert es eine ausreichend komplizierte
Widerlegung, dass man getrost davon ausgehen kann, das Laien ihr
entweder nicht folgen koennen oder nicht folgen kwerden wollen
und im Zweifelsfall kann man waehrend diese Widerlegung geschrieben
(oder gelesen) wird, locker zwanzig andere unsinnige Behauptungen
aufstellen, deren Widerlegungen ebenfalls viel mehr Zeit brauchen, als
notwendig ist, sie hervorzusprudeln.

Der Kernproblem ist allerdings immer noch die falsche Schlussfolgerung

Es ist unbekannt ob X wahr ist => X koennte wahr sein

Im zweiten Teil fehlt naemlich die Haelfte. Vollstaendig muesste er
lauten

X koennte sowohl war als auch falsch sein

was keine Schlussfolgerung ist sondern eine Wiederholung der
Praemisse. Etwas formeller ausgedrueckt,

a || !a

ist eine Tautologie. Erkenntnisse ergeben sich aus 'alles ist entweder
schwarz oder nicht schwarz' allerdings keine.



Message has been deleted
0 new messages