Anmerkung: Diese Mail sollte seit fast einem Tag bereits in der Liste sein, ist aber, auch laut http://marc.theaimsgroup.com/?l=suse-programming&r=1&b=200312&w=2 nicht angekommen. Ich poste nochmal. Laut obiger Adresse ist es auch recht selten, daß 3 Tage lang keine einzige Mail in dieser Liste auftaucht. Vieleicht klemmte da was, denn heute kam auch von jemand anders wieder was (eclipse + cvs) Hallo, Ich komme da bei einer Sache nicht weiter... Ich bastele wieder an meiner Fontsammlung rum, und wie gehabt gibt es das Problem, dass ein beschädigter Font mein Perlscript per Segfault crashen kann. Ich möchte aber das Script weiterlaufen lassen. Ich habe hier den Tip bekommen, daß das Abfangen von Segfault-Signalen unsauber wäre, da der Prozess sich in einem mehr oder weniger undefinierten Zustand befände. Besser wäre es, einen separaten Prozess zu nutzen, und den wenn der wegbricht, ihn in Frieden sterben zu lassen und einen neuen Prozess zu starten. Joo... klingt gut. Krieg ich aber nicht hin. Hier mal etwas Pseudocode: fork() if parent gib_child_kommandos() if (child weggebrochen) fork nochmal if ich_bin_plötzlich_child: raus hier # Könnte wg. fork passieren endif if child höre auf parent, führe dessen kommandos aus simuliere_crash # mit chance von 30% endif Soweit die Theorie. In der Praxis funktioniert das prima, bis tatsächlich ein Fehler im Child-Block auftritt. Derzeit simuliere ich das einfach über ein "die" mit 30%-Chance. Es scheint, als würde ein "die" im Child auch den Parent sofort beenden. Verstehe ich nicht. Steht in der Doku anders. Geguckt habe ich bisher in der perldoc unter perlipc und perlfork, große Teile des Scriptes sind den Beispielen dort entnommen. Ich füge das Script mal bei. Danke für eure Hilfe! Gruß, Ratti #!/usr/bin/perl -w use warnings; use strict; use Socket; use IO::Handle; use POSIX ":sys_wait_h"; use POSIX 'setsid'; # thousands of lines just for autoflush :-( # We say AF_UNIX because although *_LOCAL is the # POSIX 1003.1g form of the constant, many machines # still don't have it. my ($pid,$line); my ($kid,$parent); new_socket(); my $kid_pid = fork_kid(); if ( $parent ) { #parent my $alive; for ( my $i=0 ; ( $i<20 ) && ( $kid == 0) ; $i++) { $alive=kid_alive($kid_pid); if ($alive) { print CHILD "DO\n"; } else { new_socket(); $kid_pid=fork_kid(); } sleep 1; } # maybe we forked because kid died, # so "kid" can occur in parent process. # Get out here, go kid. if ( $parent ) { print "died as parent\n"; print CHILD "DIE\n"; waitpid($kid_pid,0); } if ( $kid ) { print "died as kid\n"; } } if ($kid) { #child while (1) { $line = <PARENT>; chomp $line; if ( $line eq "HELLO" ) { print PARENT "SMACK\n"; } if ( $line eq "DO" ) { if ( int(rand(100)) < 30 ) { die "e\n"; } } if ( $line eq "DIE" ) { close PARENT; exit; } } } sleep 4; sub fork_kid { $pid = fork; if ($pid != 0) { #parent close PARENT; $parent=-1; $kid=0; return $pid; } else { #kid die "cannot fork: $!" unless defined $pid; close CHILD; setsid or die "Can't start a new session: $!"; $parent=0; $kid=-1; return 0; } } sub kid_alive { my $pid=shift; if (! defined $pid ) { return 0; } # Undefined pid: Never forked before my $kid = waitpid( $pid , WNOHANG); if ( $kid == -1 ) { return 0; } # No such process # Found a(!) process. Is it the right one? print CHILD "HELLO\n"; chomp(my $line = <CHILD>); if ( $line eq "SMACK" ) { return -1; } # Kid's alive and replies return 0; # Uh. Rang the wrong door, or kid's dead. } sub new_socket { socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!"; CHILD->autoflush(1); PARENT->autoflush(1); } -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Moin moin, Am Friday 26 December 2003 14:04 schrieb Joerg Rossdeutscher:
Ich komme da bei einer Sache nicht weiter...
Ich bastele wieder an meiner Fontsammlung rum, und wie gehabt gibt es das Problem, dass ein beschädigter Font mein Perlscript per Segfault crashen kann. Ich möchte aber das Script weiterlaufen lassen.
Suchst Du etwas wie "try / catch"? In de.comp.lang.perl.* habe ich dort mal eine Nachbildung mit "eval" gesehen ... Da taucht auch dieser Link auf ... http://search.cpan.org/~pjordan/Exception-1.4/Exception.pm [...] Vielleicht hilft Dir das weiter ... Der Link zu google groups ist auch noch sehr interessant. (Sorry, wegen der Länge > 68) http://groups.google.de/groups?hl=de&lr=&ie=UTF-8&threadm=m2d71xfe7o.fsf%40phemker.de&rnum=1&prev=/groups%3Fq%3Dsegfault%2Bin%2Bchild%2Bgroup:de.comp.lang.perl.*%26hl%3Dde%26lr%3D%26ie%3DUTF-8%26group%3Dde.comp.lang.perl.*%26selm%3Dm2d71xfe7o.fsf%2540phemker.de%26rnum%3D1 Ciao Andre
Moin, Am Fr, den 26.12.2003 schrieb Andre Heine um 21:11:
Am Friday 26 December 2003 14:04 schrieb Joerg Rossdeutscher:
Ich bastele wieder an meiner Fontsammlung rum, und wie gehabt gibt es das Problem, dass ein beschädigter Font mein Perlscript
Suchst Du etwas wie "try / catch"?
In de.comp.lang.perl.* habe ich dort mal eine Nachbildung mit "eval" gesehen ...
Danke für deine Hilfe, aber das langt nicht. Es geht nicht um kleine Vertipper oder "Teilen durch 0", die ich abfangen muß, sondern um solide Segmentation Faults. Das versetzt den Prozess in einen Schrottzustand. man kann das zwar abfangen, aber das Programm macht danach nur noch Blech. Sterben lassen und mit der nächsten Datei weitermachen ist da schon richtig. Nur eben die Kommunikation zwischen den Prozessen macht mir Probleme. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Moin Ratti, Am Friday 26 December 2003 21:58 schrieb Joerg Rossdeutscher:
Am Fr, den 26.12.2003 schrieb Andre Heine um 21:11:
Am Friday 26 December 2003 14:04 schrieb Joerg Rossdeutscher:
Ich bastele wieder an meiner Fontsammlung rum, und wie gehabt gibt es das Problem, dass ein beschädigter Font mein Perlscript
Suchst Du etwas wie "try / catch"?
In de.comp.lang.perl.* habe ich dort mal eine Nachbildung mit "eval" gesehen ...
Danke für deine Hilfe, aber das langt nicht. Es geht nicht um kleine Vertipper oder "Teilen durch 0", die ich abfangen muß,
Ich weiss leider nicht genau, wie sich da Perl verhält. Aber in C/C++ oder Java kann man mit "try/catch" genau solche Sachen machen :)
sondern um solide Segmentation Faults. Das versetzt den Prozess in einen Schrottzustand. man kann das zwar abfangen, aber das Programm macht danach nur noch Blech.
Die Sache mit dem Undefinierten Zustand?
Sterben lassen und mit der nächsten Datei weitermachen ist da schon richtig. Nur eben die Kommunikation zwischen den Prozessen macht mir Probleme.
Ich würde an Deiner Stelle mal einen Perl-Guru aus Deiner Nähe fragen (de.comp.lang.perl.*). Ich habe mal in Zusammenhang mit Deinem Problem gegoogelt, mehr als eval() habe ich ich da auch nicht gefunden. Ich habe viele Threads über das "killen von subchilds" gelesen, da gibt's bestimmt noch ein paar Hints für Dich. Ciao Andre
On Sat, 27 Dec 2003 at 13:33 (+0100), Andre Heine wrote:
Am Friday 26 December 2003 21:58 schrieb Joerg Rossdeutscher:
Am Fr, den 26.12.2003 schrieb Andre Heine um 21:11:
Am Friday 26 December 2003 14:04 schrieb Joerg Rossdeutscher:
Ich bastele wieder an meiner Fontsammlung rum, und wie gehabt gibt es das Problem, dass ein beschädigter Font mein Perlscript
Suchst Du etwas wie "try / catch"?
In de.comp.lang.perl.* habe ich dort mal eine Nachbildung mit "eval" gesehen ...
Danke für deine Hilfe, aber das langt nicht. Es geht nicht um kleine Vertipper oder "Teilen durch 0", die ich abfangen muß,
Ich weiss leider nicht genau, wie sich da Perl verhält. Aber in C/C++ oder Java kann man mit "try/catch" genau solche Sachen machen :)
Einen Speicherzugriffsfehler abfangen? Wie? Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Wer viel Geld hat, kann spekulieren; wer wenig Geld hat, darf nicht spekulieren; wer kein Geld hat, muss spekulieren. -- Andre Kostelany
Moin moin, Am Saturday 27 December 2003 13:42 schrieb Bernhard Walle: [...]
Danke für deine Hilfe, aber das langt nicht. Es geht nicht um kleine Vertipper oder "Teilen durch 0", die ich abfangen muß,
Ich weiss leider nicht genau, wie sich da Perl verhält. Aber in C/C++ oder Java kann man mit "try/catch" genau solche Sachen machen :)
Einen Speicherzugriffsfehler abfangen? Wie?
Was ist den mit der berüchtigten "NullpointerException" in Java? Wird da nicht auf ein "nicht initialisiertes Objekt" zugegriffen? Also greift da Java z.B. auf Speicher zu, der nicht initialisiert ist (oder noch nicht). Ciao Andre
On Sat, 27 Dec 2003 at 14:10 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 13:42 schrieb Bernhard Walle:
[...]
Danke für deine Hilfe, aber das langt nicht. Es geht nicht um kleine Vertipper oder "Teilen durch 0", die ich abfangen muß,
Ich weiss leider nicht genau, wie sich da Perl verhält. Aber in C/C++ oder Java kann man mit "try/catch" genau solche Sachen machen :)
Einen Speicherzugriffsfehler abfangen? Wie?
Was ist den mit der berüchtigten "NullpointerException" in Java? Wird da nicht auf ein "nicht initialisiertes Objekt" zugegriffen?
Also greift da Java z.B. auf Speicher zu, der nicht initialisiert ist (oder noch nicht).
Du kannst eine Nullpointer-Exception in Java nicht mit einem Speicherzugriffsfehler in C/C++ vergleichen. Auf uninitialisierte Objekte kann man in Java nicht zugreifen, da sowas bereits der Compiler überprüft. Bsp.: // j hat irgendeinen Wert int i; if (j > 5) { i = 10; } System.out.println(i); // wird vom Compiler abgelehnt da potentiell // uninitialisiert Ein Nullzeiger ist kein uninitialisiertes Objekt. Es exisitert überhaupt kein Objekt, die Referenzvariable hat schlicht den Wert null wie in C++ ein Zeiger den Wert 0 (NULL) haben kann. Wenn Du in Java nativen Code hast gibt es auch hier das Problem eines Speicherzugriffsfehler. Die VM befindet sich dann in einem nicht definierten Status und das Programm sollte beendet werden. In C++ greift man auf einen Speicherbereich zu, der vom Betriebssystem einem anderen Prozess zugeordnet wurde. Dies wird dann vom Betriebs- system mit einem SIGSEGV abgelehnt. Das Programm befindet sich dadurch in einem potentiell undefinierten Zustand, kann noch Aufräumarbeiten durchführen und hat sich dann zu beenden. Standardmäßig beendet es sich umgehend. Eine Ausnahme wird da an keiner Stelle geworfen. Gruß, Bernhard -- "Ich dachte immer, UNIX ist was für Leute, denen es gefällt, auf einen Bildschirm zu starren, auf dem es aussieht, als hätte sich gerade ein Gürteltier auf der Tastatur gewälzt." -- Stefan Schneider
Moin moin, Am Saturday 27 December 2003 14:25 schrieb Bernhard Walle:
On Sat, 27 Dec 2003 at 14:10 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 13:42 schrieb Bernhard Walle:
[...]
Was ist den mit der berüchtigten "NullpointerException" in Java? Wird da nicht auf ein "nicht initialisiertes Objekt" zugegriffen?
Also greift da Java z.B. auf Speicher zu, der nicht initialisiert ist (oder noch nicht).
Du kannst eine Nullpointer-Exception in Java nicht mit einem Speicherzugriffsfehler in C/C++ vergleichen. Auf
Hmm...
uninitialisierte Objekte kann man in Java nicht zugreifen, da sowas bereits der Compiler überprüft.
Nun, ein "int" ist auch kein Objekt!
Bsp.:
// j hat irgendeinen Wert int i; if (j > 5) { i = 10; } System.out.println(i); // wird vom Compiler abgelehnt da potentiell // uninitialisiert
Wenn Du nun aber z.B. ein String-Objekt hast und diesen String mit etwas vergleichen möchtest. public class test { public static void main( String argv[] ){ // Dieser Code ist SUPERSCHLAMPIG und ein negativ Beispiel argv[1].equals("compse"); } } Hier meckert der Compiler definitiv nicht beim kompilieren! voodoo@yamato:~/java$ java test Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1 at test.main(test.java:18) Hier ist mein Programm Hardcore ausgestiegen, würde ich die Exception fangen, läuft das Programm eben weiter. Auch wenn hier etwas sehr undefiniertes passiert ist... Das ist nach meiner Meinung ein Speicherzugrifffehler, weil ich auf ein Array Element zugreife das nicht existiert, bzw. der Bereich mir nicht gehört. Genau hier wird eine Exception geworfen damit das Programm noch weitermachen kann (wenn man sie den fängt). Darum habe ich meine obigen Aussagen getroffen, dass dazu eben "try/catch" benutzt wird.
Ein Nullzeiger ist kein uninitialisiertes Objekt. Es exisitert überhaupt kein Objekt, die Referenzvariable hat schlicht den Wert
Wenn das Objekt nicht existiert, darf ich auch nicht darauf zugreifen, d.h. ich habe auf Speicher zugegriffen, der sonstwem gehört. Ist diese Annahme falsch?
null wie in C++ ein Zeiger den Wert 0 (NULL) haben kann. Wenn Du in Java nativen Code hast gibt es auch hier das Problem eines Speicherzugriffsfehler. Die VM befindet sich dann in einem nicht definierten Status und das Programm sollte beendet werden.
Nun, vielleicht ist ein Segfault so schwerwiegend, das das Programm beendet werden muss. Das kann ich leider nicht sagen. Ich würde trotzdem den Aufruf der nativen Methode in "try/catch" Blöcke packen und es probieren *g*. Leider habe ich heute keine Zeit mehr um dafür mal etwas Beispiel Code zu produzieren... Das werd' ich morgen mal machen und meine Erkenntnisse posten.
In C++ greift man auf einen Speicherbereich zu, der vom Betriebssystem einem anderen Prozess zugeordnet wurde. Dies wird dann vom Betriebs- system mit einem SIGSEGV abgelehnt. Das Programm befindet sich dadurch in einem potentiell undefinierten Zustand, kann noch Aufräumarbeiten durchführen und hat sich dann zu beenden. Standardmäßig beendet es sich umgehend. Eine Ausnahme wird da an keiner Stelle geworfen.
In meinem C++ Buch steht wofür ich das "exception handling" nutzen kann. Zitat aus "C++ Einführung in die professionelle Programmierung", von Breymann, Hanser Verlag. - Division durch Null - Bereichsüberschreitung eines Arrays - Syntaxfehler bei Eingaben - Zugriffe auf nicht geöffnete Dateien - Fehlschlag bei der Speicherbeschaffung - Nichteinhaltung einer Vorbedingung einer Methode Ist den ein "Fehlschlag bei der Speicherbeschaffung" kein falscher Zugriff auf den Speicher (oder ist damit nur gemeint, das zuwenig Speicher vorhanden ist, vermutlich ja *g*). Die Bereichsüberschreitungen in Arrays zähle ich dazu. Nun gut, eval() war vielleicht keine gute Idee. Try & catch vielleicht auch nicht. Ich wollte eigentlich nur ausdrücken, das wenn Fehler im try Block auftauchen, eben der catch-Block ausgeführt wird. Das macht man eben um den Fehler eventuell zu beheben oder um wenigsten jemanden zubenachrichtigen ohne das Programm zu killen. Ciao Andre
Hallo, On Sat, 27 Dec 2003 at 19:33 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 14:25 schrieb Bernhard Walle:
On Sat, 27 Dec 2003 at 14:10 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 13:42 schrieb Bernhard Walle:
[...]
uninitialisierte Objekte kann man in Java nicht zugreifen, da sowas bereits der Compiler überprüft.
Nun, ein "int" ist auch kein Objekt!
Stimmt, macht aber nichts.
Bsp.:
// j hat irgendeinen Wert int i; if (j > 5) { i = 10; } System.out.println(i); // wird vom Compiler abgelehnt da potentiell // uninitialisiert
Wenn Du nun aber z.B. ein String-Objekt hast und diesen String mit etwas vergleichen möchtest.
public class test { public static void main( String argv[] ){ // Dieser Code ist SUPERSCHLAMPIG und ein negativ Beispiel argv[1].equals("compse"); } }
Kann er ja nicht. Woher soll er denn wissen, wie lang argv ist? Und hier wird auch keine NullPointerException sondern eine ArrayIndexOutOfBoundsException kommen.
Hier meckert der Compiler definitiv nicht beim kompilieren!
voodoo@yamato:~/java$ java test Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1 at test.main(test.java:18)
Sag ich doch.
Hier ist mein Programm Hardcore ausgestiegen, würde ich die Exception fangen, läuft das Programm eben weiter.
Richtig.
Auch wenn hier etwas sehr undefiniertes passiert ist...
Nein, sehr undefiniert ist das nicht. In Java ist ein Array ein Objekt, genauso wie in C++ ein std::vector. In Java wird jeder Arrayzugriff vorher überprüft und notfalls eine ArrayIndexOutOfBoundsException geworfen. Keine Kunst, weil ja String[] ein Objekt ist und kein Zeiger auf irgendwas wie klassische C-Arrays. Bei einem std::vector kannst Du auch statt des Indexoperators die at()-Methode verwenden, welche Indexzugriffe genauso überprüft und notfalls eine std::out_of_range Ausnahme wirft.
Das ist nach meiner Meinung ein Speicherzugrifffehler, weil ich auf ein Array Element zugreife das nicht existiert, bzw. der Bereich mir nicht gehört.
Nein. Auf den Speicher wird nicht zugegriffen. Java merkt sich intern die Größe des Arrays (deshalb gibt es ein args.length) und vergleich halt bei jedem Zugriff, ob Du Dich innerhalb der Schranken befindest. Bei Rattis Problem geht es um einen SIGSEGV. Da wird über Perl auf C-Code zugegriffen und dieser Code produziert einen echten Speicher- zugriffsfehler. Das Betriebssystem schickt an den Prozess ein SIGSEGV Signal mit der Aufforderung, dass das Programm beendet wird.
Ein Nullzeiger ist kein uninitialisiertes Objekt. Es exisitert überhaupt kein Objekt, die Referenzvariable hat schlicht den Wert
Wenn das Objekt nicht existiert, darf ich auch nicht darauf zugreifen, d.h. ich habe auf Speicher zugegriffen, der sonstwem gehört.
Ist diese Annahme falsch?
Ja. Der Zeiger (die Referenz) zeigt ja nicht irgendwohin auf Speicher, dem keiner gehört sondern er hat den Wert null. Bei jeder Indirektion (Methodenaufruf, Elementzugriff) wird von der JVM geprüft, ob es sich um einen null-Zeiger handelt. Wenn ja, dann wird eine NullPointerException geworfen, bevor es zu dem Zugriff überhaupt kommt, d. h. bevor das Betriebssystem was davon mitbekommen würde.
In C++ greift man auf einen Speicherbereich zu, der vom Betriebssystem einem anderen Prozess zugeordnet wurde. Dies wird dann vom Betriebs- system mit einem SIGSEGV abgelehnt. Das Programm befindet sich dadurch in einem potentiell undefinierten Zustand, kann noch Aufräumarbeiten durchführen und hat sich dann zu beenden. Standardmäßig beendet es sich umgehend. Eine Ausnahme wird da an keiner Stelle geworfen.
In meinem C++ Buch steht wofür ich das "exception handling" nutzen kann.
Zitat aus "C++ Einführung in die professionelle Programmierung", von Breymann, Hanser Verlag.
- Division durch Null - Bereichsüberschreitung eines Arrays - Syntaxfehler bei Eingaben - Zugriffe auf nicht geöffnete Dateien - Fehlschlag bei der Speicherbeschaffung - Nichteinhaltung einer Vorbedingung einer Methode
Ist den ein "Fehlschlag bei der Speicherbeschaffung" kein falscher Zugriff auf den Speicher (oder ist damit nur gemeint, das zuwenig Speicher vorhanden ist, vermutlich ja *g*).
Nein. Der new-Operator kann scheitern, wenn kein Speicher mehr da ist. Dann wirft dieser Operator eine std::bad_alloc-Ausnahme. Wenn Du die Ausnahme abfängst und trotzdem weitermachst und auf den nicht beschafften Speicher zugreifst, bekommst Du wieder einen SIGSEGV, den Du nicht mehr abfangen kannst (außer über Signal handling). Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Win95 is not a virus; a virus does something.
Moin moin, Am Saturday 27 December 2003 19:55 schrieb Bernhard Walle:
On Sat, 27 Dec 2003 at 19:33 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 14:25 schrieb Bernhard Walle:
On Sat, 27 Dec 2003 at 14:10 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 13:42 schrieb Bernhard Walle:
[...]
Bei Rattis Problem geht es um einen SIGSEGV. Da wird über Perl auf C-Code zugegriffen und dieser Code produziert einen echten Speicher- zugriffsfehler. Das Betriebssystem schickt an den Prozess ein SIGSEGV Signal mit der Aufforderung, dass das Programm beendet wird.
Ok. Diesen Umstand hab' ich übersehen ;( Ich dachte an ein Java Programm von der Arbeit, wo ich externe Programme, Skripte, etc starten in der shell starten musste. Einige Programme haben sich mit Segfault beendet, meins musste aber weiterlaufen... Das hat funktioniert mit try & catch, dachte ich bis heute jedenfalls ;((
In C++ greift man auf einen Speicherbereich zu, der vom Betriebssystem einem anderen Prozess zugeordnet wurde. Dies wird dann vom Betriebs- system mit einem SIGSEGV abgelehnt. Das Programm befindet sich dadurch in einem potentiell undefinierten Zustand, kann noch Aufräumarbeiten durchführen und hat sich dann zu beenden. Standardmäßig beendet es sich umgehend. Eine Ausnahme wird da an keiner Stelle geworfen.
Das aufrufende Programm wird ja nicht unbedingt mitgekillt. [...]
Ist den ein "Fehlschlag bei der Speicherbeschaffung" kein falscher Zugriff auf den Speicher (oder ist damit nur gemeint, das zuwenig Speicher vorhanden ist, vermutlich ja *g*).
Nein. Der new-Operator kann scheitern, wenn kein Speicher mehr da ist. Dann wirft dieser Operator eine std::bad_alloc-Ausnahme. Wenn Du die Ausnahme abfängst und trotzdem weitermachst und auf den nicht beschafften Speicher zugreifst, bekommst Du wieder einen SIGSEGV, den Du nicht mehr abfangen kannst (außer über Signal handling).
Genau, darum werden ja "Ausnahmen geworfen". Man soll nicht mehr auf diese Variable zugreifen. Ciao Andre
Hallo Andre, On Sun, 28 Dec 2003 at 03:30 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 19:55 schrieb Bernhard Walle:
On Sat, 27 Dec 2003 at 19:33 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 14:25 schrieb Bernhard Walle:
On Sat, 27 Dec 2003 at 14:10 (+0100), Andre Heine wrote:
Am Saturday 27 December 2003 13:42 schrieb Bernhard Walle:
[...]
Bei Rattis Problem geht es um einen SIGSEGV. Da wird über Perl auf C-Code zugegriffen und dieser Code produziert einen echten Speicher- zugriffsfehler. Das Betriebssystem schickt an den Prozess ein SIGSEGV Signal mit der Aufforderung, dass das Programm beendet wird.
Ok. Diesen Umstand hab' ich übersehen ;(
Ich dachte an ein Java Programm von der Arbeit, wo ich externe Programme, Skripte, etc starten in der shell starten musste.
Einige Programme haben sich mit Segfault beendet, meins musste aber weiterlaufen...
Funktioniert doch sowieso, hab's gerade mal ausprobiert.
===================================================================
import java.io.IOException;
class Extern
{
public static void main (String[] args)
{
System.out.println("Starte Testprogramm ...");
Process p = null;
try
{
p = Runtime.getRuntime().exec("acroread");
p.waitFor();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("Fortgefaren");
}
}
===================================================================
Wenn ich das Programm mit "killall -SEGV acroread" abschieße, und das
dürfte das gleiche wie ein "echter" Speicherzugriffsfehler sein, wird
keine Exception geworfen und mit "Fortgefahren" weitergemacht.
Dann habe ich mal weil's so schön ist nativen Code geschrieben und darin
absichtlich ein Speicherzugriffsfehler produziert:
======= Native.java ================================================
import java.io.*;
class Native
{
static
{
System.loadLibrary("native");
}
public static native double nativeSqrt(double d);
public static void main (String[] args) throws IOException
{
System.out.println("Zahl eingeben: ");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
double d = Double.parseDouble(reader.readLine());
System.out.println("Java-Wurzel von " + d + " = " + Math.sqrt(d));
try
{
System.out.println("Native Wurzel von " + d + " = " + nativeSqrt(d));
}
catch (Throwable t)
{
System.out.println("t gefangen: " + t.getMessage());
}
}
}
======================================================================
======= Native.cc ====================================================
#include
Ist den ein "Fehlschlag bei der Speicherbeschaffung" kein falscher Zugriff auf den Speicher (oder ist damit nur gemeint, das zuwenig Speicher vorhanden ist, vermutlich ja *g*).
Nein. Der new-Operator kann scheitern, wenn kein Speicher mehr da ist. Dann wirft dieser Operator eine std::bad_alloc-Ausnahme. Wenn Du die Ausnahme abfängst und trotzdem weitermachst und auf den nicht beschafften Speicher zugreifst, bekommst Du wieder einen SIGSEGV, den Du nicht mehr abfangen kannst (außer über Signal handling).
Genau, darum werden ja "Ausnahmen geworfen". Man soll nicht mehr auf diese Variable zugreifen.
Ja, Du kannst mit Ausnahmebehandlung Speicherzugriffsfehler vermeiden (was auch über den Rückgabewert NULL wie bei malloc() möglich wäre, nur halt wesentlich unkomfortabler), aber Du kannst sie nicht abfangen, wenn sie bereits passiert sind. Das ist ein wesentlicher Unterschied. In Java sollte es bis auf nativen Code (s.o.) keine Speicherzugriffs- fehler geben, weil die Sprache und die JVM so designed wurden, dass man keine Low-Level-Speicheroperationen durchführen kann. In reinem Perl kann man auch keine Speicherzugriffsfehler produzieren, Ratti verwendet aber eine Bibliothek, die auf C(/C++)-Code zurückgreift. Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Es ist ein großer Vorteil im Leben, die Fehler, aus denen man lernen kann, möglichst früh zu begehen. -- Sir Winston Churchil
Am Sunday 28 December 2003 13:28 schrieb Bernhard Walle: [...Code von Berhard...] Sehr gut, das habe ich jetzt selber ausprobiert (Das Ergebnis hätte ich nicht erwartet;( ).
In Java sollte es bis auf nativen Code (s.o.) keine Speicherzugriffs- fehler geben, weil die Sprache und die JVM so designed wurden, dass man keine Low-Level-Speicheroperationen durchführen kann. In reinem Perl kann man auch keine Speicherzugriffsfehler produzieren, Ratti verwendet aber eine Bibliothek, die auf C(/C++)-Code zurückgreift.
Startet man in perl z.B . mit system() einen anderen Prozess, wenn der neue Prozess nun mit segfault wegbricht, sollte der Aufrufer korrekt weiterarbeiten. Dachte bislang, das ein SEGV nur den aktuellen Prozess killt, auch bei fork(). Anscheinend gibt es gravierende Unterschiede ob man direkt fork() benutzt anstatt system() oder exec(). In der PerlBibel steht auch, das system() & Co. mehr "arbeitet" als fork()! Wenn man mit fork arbeitet sollte wait/waitpid benutzt werden, ausserdem muss man sich selber um das aufräumen der Zombies kümmern. Es gibt vielleicht die Möglichkeit seine Prozessgruppen Nummer zu ändern damit die Childs so nicht mehr wirklich zu dem Parentprozess gehören. In der Bibel steht das allerdings in Zusammenhang, wenn man SIgnale senden möchte. Auszug: "Selbst wenn diese Prozesse eigene Child-Prozesse anstossen, findet ein HUB Signal an die Prozessgruppe sie alle (ausser denen, die Ihre eigenen Prozessgruppen gesetzt haben, um sich selbst diplomatische Immunität gegenüber Ihren Signalen zu verschaffen)." Irgendwie hört sich das interessant und verbiegbar an :) Das sind bislang meine Erfahrungen zu diesem Thema... Vielleicht ist es die einfachste Möglichkeit, das Programm in zwei Teile zu trennen, ob das schön ist lasse ich jetzt mal dahingestellt. (Mit system()) Ich denke aber das Ratti trotzalledem mal eval() ausprobieren sollte, die Sache mit dem Pragma hört sich im Buch auch sehr nett an. Obwohl mich diese Diskussion sehr daran zweifeln lässt, das das funktioniert ;( Leider habe ich keine Ahnung von Fonts, deshalb ist folgenden Aussage mit vorsicht zu geniessen. IMHO würde der ganze Kram nicht anfallen, wenn man den Font korrekt überprüfen könnte und damit den segfault vermeidet. (Bitte nicht lachen) Ratti schreibt, das er den Font an freetype übergibt. Wie/womit machst er das? C in Perl? Ein Modul das in C geschrieben ist? Ciao Andre
Moin, Am So, den 28.12.2003 schrieb Andre Heine um 18:04:
Ich denke aber das Ratti trotzalledem mal eval() ausprobieren sollte, die Sache mit dem Pragma hört sich im Buch auch sehr nett an.
Das fesselt dich anscheinend... :-) Natürlich war eval das erste, was ich ausprobiert habe, danach auch etwas härtere Geschütze. :-)
Obwohl mich diese Diskussion sehr daran zweifeln lässt, das das funktioniert ;(
Eine gute Nachricht: Du hast Recht. :-)))
Leider habe ich keine Ahnung von Fonts, deshalb ist folgenden Aussage mit vorsicht zu geniessen.
IMHO würde der ganze Kram nicht anfallen, wenn man den Font korrekt überprüfen könnte und damit den segfault vermeidet. (Bitte nicht lachen)
"Fonts" sind in diesem Fall PostScript- bzw. OpenType-Fonts. Bei beiden Formaten handelt es sich (jeweils!) praktisch um eine komplette Sprache. Das ist, als würde mein Programm ein beliebiges Script starten dürfen und ich müsste vorher garantieren, dass es ohne Fehler läuft - nicht machbar. Fonts gehören zu den komplexesten Dateiformaten, die mir jeweils untergekommen sind. Bestimmt können andere das toppen. Aber das ist schon krass.
Ratti schreibt, das er den Font an freetype übergibt. Wie/womit machst er das?
C in Perl? Ein Modul das in C geschrieben ist?
ImageMagick, bzw. das perl-Modul dafür. IM wiederum verwendet freetype und ghostscript. Anbei etwas fragmentarischen Beispielcode: my $image; my $background='#ffffff'; $image=Image::Magick->new( size => '450x120', background => $background, depth => 8); $image->ReadImage("xc:$background"); $image->Annotate( x => 0, y => 90, pointsize => 90, font => $filename, antialias => 1, fill => 'black', undercolor => $background, text => 'Fontlinge äöüß' ); $image->Write("$image_name"); undef $image; Der "Annotate"-Befehl schreibt einen Text als Bild in ein Image. Dabei kann man nicht nur installierte Fonts angeben, sondern, und das brauche ich, eine beliebige, nicht installierte Fontdatei. Auf die Art erzeuge ich ein paar zehntausend Previews. Siehe Signatur. :-) Bevor die Idee aufkommt: Aufgrund der großen Anzahl der Aufrufe ist ein externes Skript in Backticks nicht akzeptabel. Es würde mehrere zehntausend mal perl starten. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Moin, Am Sunday 28 December 2003 19:19 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 18:04:
Ich denke aber das Ratti trotzalledem mal eval() ausprobieren sollte, die Sache mit dem Pragma hört sich im Buch auch sehr nett an.
Das fesselt dich anscheinend... :-)
Ja, irgendwie schon. Habe gedacht, das das alles nicht so ein Problem sein kann... Ausserdem habe ich wiedermal viel gelernt (ist doch 'nen Problem)!
Natürlich war eval das erste, was ich ausprobiert habe, danach auch etwas härtere Geschütze. :-)
Was für härtere Geschütze?
Obwohl mich diese Diskussion sehr daran zweifeln lässt, das das funktioniert ;(
Eine gute Nachricht: Du hast Recht. :-)))
Ich verstehe halt ein Sache nicht, warum macht das z.B. der Aufruf von "system()" mit einem externen Programm richtig und fork() nicht. IIRC hast Du geschrieben, das Du wegen "unsauber" die Signale nicht abfangen möchtest, aber das würde funktionieren meinst Du. Was ist da so "unsauber" dran, in der BIbel wird das mit dem Abfangen ja zuhauf erklärt. Scheint so, das das mehrere machen.
IMHO würde der ganze Kram nicht anfallen, wenn man den Font korrekt überprüfen könnte und damit den segfault vermeidet. (Bitte nicht lachen)
"Fonts" sind in diesem Fall PostScript- bzw. OpenType-Fonts. Bei beiden Formaten handelt es sich (jeweils!) praktisch um eine komplette Sprache.
Hmm, in der Tat wäre es ein RIESEN Aufwand den Font zu prüfen.
Das ist, als würde mein Programm ein beliebiges Script starten dürfen und ich müsste vorher garantieren, dass es ohne Fehler läuft - nicht machbar.
Nicht machbar? Habe mal gehört das man das nicht sagen soll *g*. Du hast Recht, die Fonts zu überprüfen würde ein etwas grösseres Programm verlangen.
Ratti schreibt, das er den Font an freetype übergibt. Wie/womit machst er das?
C in Perl? Ein Modul das in C geschrieben ist? ImageMagick, bzw. das perl-Modul dafür. IM wiederum verwendet
Joo, jetzt kapiere ich Dein Problem etwas besser.
Bevor die Idee aufkommt: Aufgrund der großen Anzahl der Aufrufe ist ein externes Skript in Backticks nicht akzeptabel. Es würde mehrere zehntausend mal perl starten.
Oder die shell... Den Grund verstehe ich, aber so würden jedenfalls weniger "undefinierte" Sachen auftauchen. Irgendwie musst Du ja das Programm stabil kriegen. Keine Signale abfangen, keine zwei Programme, was bleibt da dann noch? Mich interessiert das jetzt wirklich, weil diese Situation könnte mich auch bald treffen ;( Ciao Andre
Hi, Am So, den 28.12.2003 schrieb Andre Heine um 20:03:
Am Sunday 28 December 2003 19:19 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 18:04:
Natürlich war eval das erste, was ich ausprobiert habe, danach auch etwas härtere Geschütze. :-)
Was für härtere Geschütze?
%SIG. Siehe perlipc und perlvar, suche nach "%SIG". Woran ich lange getüftelt habe: Nach einem Segfault geht eine ganze Kaskade von Signalen auf das Script nieder, die mit unterschiedlicher Priorität zur Beendigung auffordern. Wenn man einen Segfault abfangen will, muß daher ein normales Quit auch noch abfangen. Wenn du damit rumprobieren willst, setze einfach testweise(!) *alle* Signalhandler auf "Abfangen", um einen Überblick zu bekommen.
Ich verstehe halt ein Sache nicht, warum macht das z.B. der Aufruf von "system()" mit einem externen Programm richtig und fork() nicht.
Das weiss ich nicht, weil ich damit bisher keine Probleme hatte, weil ich es mit "system" nicht mache(n kann). Mit "fork" habe ich das Problem (noch) nicht, da sich dieser Thread geflissentlich in eine andere Richtung entwickelt hat. (Da sind noch zwei Mails gewesen von Thorsten und von dir, die gute Hinweise enthalten. Ich nehme mir die in Ruhe vor, ich laboriere gerade an einer Erkältung).
IIRC hast Du geschrieben, das Du wegen "unsauber" die Signale nicht abfangen möchtest, aber das würde funktionieren meinst Du.
Was ist da so "unsauber" dran, in der BIbel wird das mit dem Abfangen ja zuhauf erklärt. Scheint so, das das mehrere machen.
Ok. Pseudocode: on SEGFAULT goto WEITER for ( $i von 1 bis 30 ) { mein_speicher = malloc (10000) machwas(mein_speicher) free(mein_speicher) WEITER: } sub machwas { gefaehrlicher_befehl_hier } Sowas kannst du programmieren. Im Falle eines Segfaults in "machwas" macht das Programm bei WEITER weiter. Definiere: Ist "mein_speicher" jetzt freigegeben oder belegt? Ist der Stapelspeicher, der die Schleifen verwaltet, in einem definierten Zustand? Oder liegen da Leichen rum? Und, da Zugriffsfehler auf Prozessorebene ausgelöst werden: Verhält sich da jedes System gleich? Läuft mein Script auch noch unter OS X auf einem PowerMac? Unter Windows? Das Abfangen von Segfaults macht Sinn, um noch schnell eine Datei zu schliessen, vieleicht ein Tempfile zu löschen und danach selbst zu exit'en. Mehr nicht. Das komplette Beenden des Prozesses führt dann dazu, daß das System alles wieder freigibt, was dieser Prozess angefordert hat. Erst jetzt ist die Kiste wieder clean.
Bevor die Idee aufkommt: Aufgrund der großen Anzahl der Aufrufe ist ein externes Skript in Backticks nicht akzeptabel. Es würde mehrere zehntausend mal perl starten.
Oder die shell...
Jedenfalls was großes.
Den Grund verstehe ich, aber so würden jedenfalls weniger "undefinierte" Sachen auftauchen.
Ja. Aber. Derzeit habe ich in meiner Sammlung knapp 165.000 Fonts. Wie gefällt dir dieser Code: for ( $i = 0 ; $i < 165000 ; $i++ ) { `machwas.pl $font[$i]`; } Also, mir schmeckt das nicht besonders. Ich habe was dagegen, wenn meine Software über mein natürliches Ableben hinaus läuft. :-)
Irgendwie musst Du ja das Programm stabil kriegen.
Keine Signale abfangen, keine zwei Programme, was bleibt da dann noch? Mich interessiert das jetzt wirklich, weil diese Situation könnte mich auch bald treffen ;(
fork'en. Darauf will ich ja die ganze Zeit hinaus. Ich habe lediglich schon ein Problem mit ganz normaler Kommunikation zwischen zwei Prozessen. Der gefork'te beendet sich ganz normal und sauber, und plötzlich ist mein parent auch wech. Ich muß die Mail von Thorsten nochmal ohne Brummschädel durcharbeiten. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Hallo, Ich möchte nur einen ganz einfachen Vorschlag dazu abgeben. Ich bitte um Verzeihung, falls er vollkommen schwachsinnig ist. Am Sonntag, 28. Dezember 2003 22:39 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 20:03:
Am Sunday 28 December 2003 19:19 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 18:04:
Lauter ge%SIGge...
on SEGFAULT goto WEITER
for ( $i von 1 bis 30 ) { mein_speicher = malloc (10000) machwas(mein_speicher) free(mein_speicher) WEITER: }
sub machwas { gefaehrlicher_befehl_hier }
Sowas kannst du programmieren. Im Falle eines Segfaults in "machwas" macht das Programm bei WEITER weiter. Definiere: Ist "mein_speicher" jetzt freigegeben oder belegt? Ist der Stapelspeicher, der die Schleifen verwaltet, in einem definierten Zustand? Oder liegen da Leichen rum? Und, da Zugriffsfehler auf Prozessorebene ausgelöst werden: Verhält sich da jedes System gleich? Läuft mein Script auch noch unter OS X auf einem PowerMac? Unter Windows?
Zumindest unter Windows kommen Fontlinge sowieso nicht weit. Da finden die nicht mal /usr . ;-)
Das Abfangen von Segfaults macht Sinn, um noch schnell eine Datei zu schliessen, vieleicht ein Tempfile zu löschen und danach selbst zu exit'en. Mehr nicht. Das komplette Beenden des Prozesses führt dann dazu, daß das System alles wieder freigibt, was dieser Prozess angefordert hat. Erst jetzt ist die Kiste wieder clean.
Bevor die Idee aufkommt: Aufgrund der großen Anzahl der Aufrufe ist ein externes Skript in Backticks nicht akzeptabel. Es würde mehrere zehntausend mal perl starten.
Oder die shell...
Jedenfalls was großes.
Den Grund verstehe ich, aber so würden jedenfalls weniger "undefinierte" Sachen auftauchen.
Ja. Aber.
Derzeit habe ich in meiner Sammlung knapp 165.000 Fonts. Wie gefällt dir dieser Code:
for ( $i = 0 ; $i < 165000 ; $i++ ) { `machwas.pl $font[$i]`; }
Kann mach was nicht einfach einfach etwas zurück geben, wenn kein Font gefunden wurde? Also ungefähr so: my $ueberhaupt_nichts = 0; for($i = 0; $ueberhaupt_nichts == 0; $i++) { #Mit einer Pipe, da mir grade die Syntax fuer Backtics nicht einfaellt open(MACHWAS, "machwas.pl $font[$i] |"); #Irgendwie einlesen und die Ausgabe auswerten #Wenn das Perlscript kein Font mehr fand $ueberhaupt_nichts = 1 if irgendeine spezielle Ausgabe; close(MACHWAS) }
Also, mir schmeckt das nicht besonders. Ich habe was dagegen, wenn meine Software über mein natürliches Ableben hinaus läuft. :-)
Wenn das Programm auf jeden Fall immer einen Font findet oder mit einem Fehler aufhört, geht das so, da ja die Ausgabe, wenn es keinen Font findet, sich von beiden unterscheiden dürfte.
Irgendwie musst Du ja das Programm stabil kriegen.
Keine Signale abfangen, keine zwei Programme, was bleibt da dann noch? Mich interessiert das jetzt wirklich, weil diese Situation könnte mich auch bald treffen ;(
fork'en. Darauf will ich ja die ganze Zeit hinaus. Ich habe lediglich schon ein Problem mit ganz normaler Kommunikation zwischen zwei Prozessen. Der gefork'te beendet sich ganz normal und sauber, und plötzlich ist mein parent auch wech. Ich muß die Mail von Thorsten nochmal ohne Brummschädel durcharbeiten.
Geht Forken eigentlich auch unter Windows? Das müsste ja eigentlich wie kill oder waitpid Unixspezifisch sein. Ferdinand
On Mon, 29 Dec 2003 at 01:37 (+0100), Ferdinand Ihringer wrote:
Am Sonntag, 28. Dezember 2003 22:39 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 20:03:
Am Sunday 28 December 2003 19:19 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 18:04:
Irgendwie musst Du ja das Programm stabil kriegen.
Keine Signale abfangen, keine zwei Programme, was bleibt da dann noch? Mich interessiert das jetzt wirklich, weil diese Situation könnte mich auch bald treffen ;(
fork'en. Darauf will ich ja die ganze Zeit hinaus. Ich habe lediglich schon ein Problem mit ganz normaler Kommunikation zwischen zwei Prozessen. Der gefork'te beendet sich ganz normal und sauber, und plötzlich ist mein parent auch wech. Ich muß die Mail von Thorsten nochmal ohne Brummschädel durcharbeiten.
Geht Forken eigentlich auch unter Windows? Das müsste ja eigentlich wie kill oder waitpid Unixspezifisch sein.
In Perl ja. Als System call existiert es aber nicht. Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ The Internet is not a primary goal for PC usage -- Bill Gates (1995)
Hi,
* Ferdinand Ihringer
Und, da Zugriffsfehler auf Prozessorebene ausgelöst werden: Verhält sich da jedes System gleich? Läuft mein Script auch noch unter OS X auf einem PowerMac? Unter Windows?
Zumindest unter Windows kommen Fontlinge sowieso nicht weit. Da finden die nicht mal /usr . ;-)
Unter Cygwin schon.
#Mit einer Pipe, da mir grade die Syntax fuer Backtics nicht einfaellt open(MACHWAS, "machwas.pl $font[$i] |");
Ratti sagte, daß er einige Tausend Prozesse braucht. Das wäre so recht teuer, zumal jeder Prozeß ein eigenes Perl braucht.
Geht Forken eigentlich auch unter Windows? Das müsste ja eigentlich wie kill oder waitpid Unixspezifisch sein.
Soviel Posix kann selbst Windows. Thorsten -- The man who does not read good books has no advantage over the man who cannot read them. - Mark Twain
Hallo, Am Montag, 29. Dezember 2003 01:52 schrieb Thorsten Haude:
Hi,
* Ferdinand Ihringer
[2003-12-29 01:37]: Und, da Zugriffsfehler auf Prozessorebene ausgelöst werden: Verhält sich da jedes System gleich? Läuft mein Script auch noch unter OS X auf einem PowerMac? Unter Windows?
Zumindest unter Windows kommen Fontlinge sowieso nicht weit. Da finden die nicht mal /usr . ;-)
Unter Cygwin schon.
Wird da auch für X das Fontverzeichnis richtig emuliert, sodass da alle Windows Fonts drin sind? Cygwin nutzte ich bisher nur mal mit einer recht minimalen Installation.
#Mit einer Pipe, da mir grade die Syntax fuer Backtics nicht einfaellt open(MACHWAS, "machwas.pl $font[$i] |");
Ratti sagte, daß er einige Tausend Prozesse braucht. Das wäre so recht teuer, zumal jeder Prozeß ein eigenes Perl braucht.
Ich bin einsichtig. Ich las mal die Zahlen von 0 bis 42000 in nur einer Schleife ausgeben und dann die Schleife ein Programm aufrufen, dem die aktuelle Zahl als Argument übergeben wird, welches es auch gleich wieder über Backtics an das eigentlich Programm zurückkommt und dieses sie dann ausgibt. Also 'print $_."\n" for(0 .. 42000);' bzw. 'print `$ARGV[0] $_` for(0 .. 42000);' und 'print $ARGV[0]."\n";'. Als erstes zum Spaß mit einer perlcc-Binärdatei: real 6m37.839s user 4m8.290s sys 1m53.250s Dann mit einem normalen Perlaufruf: real 4m38.716s user 2m15.690s sys 1m42.120s Einfach so ohne das extra Programm: real 0m2.546s user 0m0.090s sys 0m0.080s 111:1 zwischen den beiden und das extra-Script hat nur print-Aufrufe. :-| Das war jetzt aber ohne Kinder... Wenn man 42001 von denen hat. Dauert das nicht auch ein bisschen länger als alles in einer Schleife zu machen? Ferdinand
Moin,
* Ferdinand Ihringer
Am Montag, 29. Dezember 2003 01:52 schrieb Thorsten Haude:
* Ferdinand Ihringer
[2003-12-29 01:37]: Und, da Zugriffsfehler auf Prozessorebene ausgelöst werden: Verhält sich da jedes System gleich? Läuft mein Script auch noch unter OS X auf einem PowerMac? Unter Windows?
Zumindest unter Windows kommen Fontlinge sowieso nicht weit. Da finden die nicht mal /usr . ;-)
Unter Cygwin schon.
Wird da auch für X das Fontverzeichnis richtig emuliert, sodass da alle Windows Fonts drin sind? Cygwin nutzte ich bisher nur mal mit einer recht minimalen Installation.
Das weiß ich nicht, ich habe das auch nur mal installiert, um einen vernünftigen Editor nutzen zu können (um - ürgs - Visual Basic zu programmieren). Der Rest hat mich nicht interessiert. Thorsten -- Try not to be a man of success but rather of value. - Albert Einstein
moin moin, Am Sunday 28 December 2003 22:39 schrieb Joerg Rossdeutscher:
Am So, den 28.12.2003 schrieb Andre Heine um 20:03:
Keine Signale abfangen, keine zwei Programme, was bleibt da dann noch? Mich interessiert das jetzt wirklich, weil diese Situation könnte mich auch bald treffen ;(
fork'en. Darauf will ich ja die ganze Zeit hinaus. Ich habe lediglich schon ein Problem mit ganz normaler Kommunikation
Vielleicht fork, eigentlich möchte ich Threads in C++ nutzen. Es geht darum, das dynamisch Librarys geladen werden sollen. Diese Module können natürlich (wie bei Deinen Fonts) 'ne Menge Mist veranstalten. Ich möchte natürlich nicht, dass ein SEGV mein Programm abschiesst.
zwischen zwei Prozessen. Der gefork'te beendet sich ganz normal und sauber, und plötzlich ist mein parent auch wech. Ich muß die Mail von Thorsten nochmal ohne Brummschädel durcharbeiten.
Ich werde heute auch mal etwas forken, allerdings in C. Mal sehen auf was für Probleme ich stosse. Ciao Andre
Am Sa, den 27.12.2003 schrieb Andre Heine um 19:33:
Darum habe ich meine obigen Aussagen getroffen, dass dazu eben "try/catch" benutzt wird.
Ne, echt, kannst du knicken. Was du beschreibst, sind kontrollierte Abbrüche durch deinen Code selbst - auch wenn du ihn nicht so geschrieben hast, der Compiler sorgt dafür. Ich rede davon, daß eine defekte Schrift an freetype übergeben wird (Daß sie defekt ist, kann ich ja nicht prüfen), woraufhin freetype irgendeine (defekte) Anweisung im Fontcode ohne Prüfung ausführt und erstmal getreulich versucht, sagenwirmal 5 Okobyte RAM von der Adresse $IRSINN nach $WAHNSINN zu verschieben. Selbstredend gehört dieser Speicher nicht freetype. Der Prozessor selbst bricht an dieser Stelle die Verarbeitung des Codes wegen einer Speicherschutzverletzung ab. Alles, was der Code bis dahin ausgeführt hat, wird nicht sauber aufgeräumt. Man kann das in der Tat abfangen, indem man %SIG verbiegt, und das habe ich auch getan. Du hast dann aber schwerwiegende Nebeneffekte: Der Speicher könnte zulaufen, oder perl hat so "einen mitgekriegt", daß es 10 Zeilen später bei einer korrekten Anweisung wegbricht. Erst das Beenden des Prozesses entfernt "sauber" alles aus dem Speicher, was da jetzt krumm und schief ist. Daher die Idee: Ein Prozess startet einen zweiten Prozess, der die eigentliche Arbeit leistet. Wenn dieser Prozess Segfaultet, lass ihn wegbrechen - der erste Prozess merkt das, kennt auch die verursachende Datei und forkt einen neuen Prozess, der mit der nächsten Datei fortfährt. Ende gut, alles gut. Außer, daß es bis jetzt nicht läuft. Vielleicht darf ich die geneigten Leser kurz darauf hinweisen, daß mein Programm in der derzeitigen Form gar keine Segfaults verursacht, der zweite Prozess wird einfach zu Testzwecken mit einer 30%-Chance beendet: if rnd(100)<30 then print "Gaaanz böser Fehler"; exit; Mein Problem: Warum stirbt der Parent-Prozess mit? Wieso? Das sollte so nicht sein. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Moin Ratti, Am Saturday 27 December 2003 20:33 schrieb Joerg Rossdeutscher:
Am Sa, den 27.12.2003 schrieb Andre Heine um 19:33:
Darum habe ich meine obigen Aussagen getroffen, dass dazu eben "try/catch" benutzt wird.
Ne, echt, kannst du knicken. Was du beschreibst, sind kontrollierte Abbrüche durch deinen Code selbst - auch wenn du ihn nicht so geschrieben hast, der Compiler sorgt dafür.
[...] Das hat mir ja nun Bernhard alles verklickert :)))
Mein Problem: Warum stirbt der Parent-Prozess mit? Wieso? Das sollte so nicht sein.
Zitat aus der PerlBibel(Larry& Co.): "(Sogar die die-Routine ist etwas unsicher, solange der Prozess nicht in einem eval ausgeführt wird, der die Ein-/Ausgabe von "die" unterdrückt, was wiederum den Aufruf der C-Bibliothek verhindert. Wahrscheinlich.) Eine noch einfachere Möglichkeit, Signale abzufangen, besteht darin, das sigtrap-Pragma zu verwenden und einfache Standard-Signalhandler zu installieren. Dieses Pragma ist nützlich, wenn Sie sich nicht mit der Entwicklung eigener Handler aufhalten wollen, gefährliche Signale aber trotzdem sauber abfangen wollen und ordentlich herunterfahren möchten. " BTW, damit könnte man z.B. Signale in Ausnahmen umwandeln ... Ciao Andre
Hi Ratti, hi Liste, ich programmiere zwar schon seit Jahren nicht mehr in Perl, dieser Thread interessiert mich aber weil ich mich intensive mit "Multiprocessing" und "Multithreading" auseinander gesetzt habe, und das Problem welches hier auftaucht, ich nur vom Multithreading her kenne. Vorweg eine Definition was ich unter Multiprocessing und Multithreading versteh: _Multiprocessing:_ Das erstellen eines neuen Prozesses mit fork, der vollkommen unabhängig vom Parentprozess ist. Die einzige Kommunikation zum Parentprozess besteht über einen Returncode, der mit wait vom Parentprozess abgefragt werden kann/muß. Stirbt der Parentprozess, fängt init (Prozess# 1) den Childprozess auf, und der Childprozess wird damit zu einem Deamon. Alles an Variablen, Filedescriptoren etc. sind im Childprozess unabhängig und seperat vorhanden. _Vorteil:_ extrem robust _Nachteil:_ Alle Komunikation zwischen Parent- und ChildProzess muß seperat über sharedmemory, semaphoren oder pipes programmiert werden. _Multithreading:_ Das erstellen eiens neuen Threads mit einem in der Prog.-sprache dafür vorgesehenen Befehls, er ist nicht unabhängig, und teilt sich alle "Variablen", Filedescriptoren etc. mit den anderen Threads. _Vorteil:_ einfache Komunikation zwischen den Threads _Nachteil:_ empfindlich, der Absturz eines Threads, reißt die anderen mit, wenn es nicht programmtechnisch abgefangen wird. Multithreading kann der Linuxkernel AFAK seit 2.0, vorher war nur Multiprozessing möglich. Zurück zum Thema: Hier scheint sich genau der Nachteil vom Multithreding bemerkbar zu machen. Meine Vermutung ist, der Befehl fork in Perl startet nicht einen eigenen Prozess, sondern macht nur einen eigenen Tread im Interpreter dafür auf. Neben dem Verhalten sprechen noch einige andere Aussagen dafür: Bernhard Walle wrote:
On Mon, 29 Dec 2003 at 01:37 (+0100), Ferdinand Ihringer wrote:
Geht Forken eigentlich auch unter Windows? Das müsste ja eigentlich wie kill oder waitpid Unixspezifisch sein. In Perl ja. Als System call existiert es aber nicht.
Der kleinste gemeinsame Nenner ist hier Multithreading. Siehe auch: http://www.gsp.com/cgi-bin/man.cgi?section=1&topic=perlfork <Zitate> NOTE: As of the 5.8.0 release, fork() emulation has considerably matured. However, there are still a few known bugs and differences from real fork() that might affect you. See the "BUGS" and "CAVEATS AND LIMITATIONS" sections below. Note that the issues discussed here are not applicable to platforms where a real fork() is available _and Perl has been configured to use it._ In the eyes of the operating system, pseudo-processes created via the fork() emulation are simply threads in the same process. If the parent process is killed (either using Perl's kill() builtin, or using some external means) all the pseudo-processes are killed as well, and the whole process exits. </Zitate> Diese forkemulation gibt es seit 5.6.1. Vorher galt sie als experimentel. Kann es sein das Perl mitlerweile standardmäsig so kompiliert/configuriert wird, das es auch unter Linux dise emulation nutzt, damit es sich auf Linux und Windows (M$ hat wohl diese emulation gesponsert) gleich verhält? Joerg Rossdeutscher wrote:
Daher die Idee: Ein Prozess startet einen zweiten Prozess, der die eigentliche Arbeit leistet. Wenn dieser Prozess Segfaultet, lass ihn wegbrechen - der erste Prozess merkt das, kennt auch die verursachende Datei und forkt einen neuen Prozess, der mit der nächsten Datei fortfährt.
s. o. bist du sicher das es ein eigener Prozeß ist?
Mein Problem: Warum stirbt der Parent-Prozess mit? Wieso?
Weil es keinen Parent-Prozess gibt, sondern nur einen Thread.
Das sollte so nicht sein.
Bei einem Thread schon, nicht bei einem Prozess. hth cu Gerald
Hallo, On Mon, 29 Dec 2003 at 16:51 (+0100), Gerald Goebel wrote:
Hier scheint sich genau der Nachteil vom Multithreding bemerkbar zu machen.
Irgendwie hast Du recht.
Meine Vermutung ist, der Befehl fork in Perl startet nicht einen eigenen Prozess, sondern macht nur einen eigenen Tread im Interpreter dafür auf. Neben dem Verhalten sprechen noch einige andere Aussagen dafür:
Laut Dokumentation (perldoc -f fork): fork Does a fork(2) system call to create a new process running the same program at the same point. It returns the child pid to the parent process, 0 to the child process, or "undef" if the fork is unsuccessful. File descriptors (and sometimes locks on those descriptors) are shared, while everything else is copied. On most systems sup- porting fork(), great care has gone into making it extremely efficient (for example, using copy-on- write technology on data pages), making it the dominant paradigm for multitasking over the last few decades. Also ganz klar ein echter fork().
Bernhard Walle wrote:
On Mon, 29 Dec 2003 at 01:37 (+0100), Ferdinand Ihringer wrote:
Geht Forken eigentlich auch unter Windows? Das müsste ja eigentlich wie kill oder waitpid Unixspezifisch sein. In Perl ja. Als System call existiert es aber nicht.
Note that the issues discussed here are not applicable to platforms where a real fork() is available _and Perl has been configured to use it._
Klingt nach konfigurierbar, stimmt. ;-)
Diese forkemulation gibt es seit 5.6.1. Vorher galt sie als experimentel. Kann es sein das Perl mitlerweile standardmäsig so kompiliert/configuriert wird, das es auch unter Linux dise emulation nutzt, damit es sich auf Linux und Windows (M$ hat wohl diese emulation gesponsert) gleich verhält?
Ich habe hier SuSE 9.0 und das standardmäßige Perl (das vom Online- Update, da gab's mal was). Folgendes Testskript: ,---- | #!/usr/bin/perl | | $pid = fork(); | | if ($pid > 0) # child | { | print "I'm the child!\n"; | sleep 20; | } | elsif ($pid == 0) | { | print "I'm the parent!\n"; | sleep 20; | } | else | { | print "Could not fork: $!"; | } | | print "We do that both!\n"; `---- [~] $ perl test.pl I'm the parent! I'm the child! Auf 'ner anderen Konsole: [~] $ ps aux | grep test.pl | grep perl bwalle 12816 0.0 0.2 3584 1420 pts/3 S 17:16 0:00 perl test.pl bwalle 12817 0.0 0.2 3584 1420 pts/3 S 17:16 0:00 perl test.pl [~] $ kill -SEGV 12817 [~] $ ps aux | grep test.pl | grep perl bwalle 12816 0.1 0.2 3584 1420 pts/3 S 17:16 0:00 perl test.pl Hier also ein ganz klares fork, aber das komische ist dass es hier der Elternprozess auch nicht stibt. Ok, es ist kein echter Speicherzugriffs- fehler. Aber irgendwie ist das jetzt eine gute Gelegenheit, mal etwas C ins Spiel zu bringen *Perl-Buch rauskram* *les* *etwas später* Auch hier lebt der Parent eindeutig weiter. Strange. perl -V Summary of my perl5 (revision 5.0 version 8 subversion 1) configuration: Platform: osname=linux, osvers=2.6.0-test3, archname=i586-linux-thread-multi uname='linux g8 2.6.0-test3 #1 smp fri nov 14 00:07:01 utc 2003 i686 i686 i386 gnulinux ' config_args='-ds -e -Dprefix=/usr -Dvendorprefix=/usr -Dinstallusrbinperl -Dusethreads -Di_db -Di_dbm -Di_ndbm -Di_gdbm -Duseshrplib=true -Doptimize=-O2 -march=i586 -mcpu=i686 -fmessage-length=0 -Wall -pipe' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2 -march=i586 -mcpu=i686 -fmessage-length=0 -Wall -pipe', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -fno-strict-aliasing' ccversion='', gccversion='3.3.1 (SuSE Linux)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags ='' libpth=/lib /usr/lib /usr/local/lib libs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc libc=, so=so, useshrplib=true, libperl=libperl.so gnulibc_version='2.3.2' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.1/i586-linux-thread-multi/CORE' cccdlflags='-fPIC', lddlflags='-shared' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY USE_ITHREADS USE_LARGE_FILES PERL_IMPLICIT_CONTEXT Built under linux Compiled at Dec 10 2003 09:22:12 @INC: /usr/lib/perl5/5.8.1/i586-linux-thread-multi /usr/lib/perl5/5.8.1 /usr/lib/perl5/site_perl/5.8.1/i586-linux-thread-multi /usr/lib/perl5/site_perl/5.8.1 /usr/lib/perl5/site_perl /usr/lib/perl5/vendor_perl/5.8.1/i586-linux-thread-multi /usr/lib/perl5/vendor_perl/5.8.1 /usr/lib/perl5/vendor_perl . Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ At least Microsoft offers updates to keep your selection of bugs fresh. -- Alan Shutko, hating Corel even more, in asr
Bernhard Walle wrote:
Hallo,
On Mon, 29 Dec 2003 at 16:51 (+0100), Gerald Goebel wrote:
Hier scheint sich genau der Nachteil vom Multithreding bemerkbar zu machen.
Irgendwie hast Du recht.
leider ;-(
Meine Vermutung ist, der Befehl fork in Perl startet nicht einen eigenen Prozess, sondern macht nur einen eigenen Tread im Interpreter dafür auf. Neben dem Verhalten sprechen noch einige andere Aussagen dafür:
Laut Dokumentation (perldoc -f fork):
fork Does a fork(2) system call to create a new process running the same program at the same point. It returns the child pid to the parent process, 0 to the child process, or "undef" if the fork is unsuccessful. File descriptors (and sometimes locks on those descriptors) are shared, while everything else is copied. On most systems sup- porting fork(), great care has gone into making it extremely efficient (for example, using copy-on- write technology on data pages), making it the dominant paradigm for multitasking over the last few decades.
Also ganz klar ein echter fork().
Bist du dir sicher das dieses nicht auch in der Windoof-Version steht?
Diese forkemulation gibt es seit 5.6.1. Vorher galt sie als experimentel. Kann es sein das Perl mitlerweile standardmäsig so kompiliert/configuriert wird, das es auch unter Linux dise emulation nutzt, damit es sich auf Linux und Windows (M$ hat wohl diese emulation gesponsert) gleich verhält?
Ich habe hier SuSE 9.0 und das standardmäßige Perl (das vom Online- Update, da gab's mal was).
ich SuSe 8.0 und Perl 5.6.1
Folgendes Testskript:
,---- | #!/usr/bin/perl | | $pid = fork(); | | if ($pid > 0) # child
das ist der Parent
| { | print "I'm the child!\n"; | sleep 20; | } | elsif ($pid == 0) | {
das ist das Child siehe perldoc -f fork SCNR
| print "I'm the parent!\n"; | sleep 20; | } | else | { | print "Could not fork: $!"; | } | | print "We do that both!\n"; `----
[~] $ perl test.pl I'm the parent! I'm the child!
Auf 'ner anderen Konsole:
[~] $ ps aux | grep test.pl | grep perl bwalle 12816 0.0 0.2 3584 1420 pts/3 S 17:16 0:00 perl test.pl bwalle 12817 0.0 0.2 3584 1420 pts/3 S 17:16 0:00 perl test.pl
[~] $ kill -SEGV 12817 [~] $ ps aux | grep test.pl | grep perl bwalle 12816 0.1 0.2 3584 1420 pts/3 S 17:16 0:00 perl test.pl
Bei mir wird das Child auch zum Deamon ppid == 1.
Hier also ein ganz klares fork, aber das komische ist dass es hier der Elternprozess auch nicht stibt. Ok, es ist kein echter Speicherzugriffs- fehler.
Naja, der Fehler wird doch nicht durchgereicht, sondern nur das Signal das durch den Fehler erzeugt wird, oder? Und den gibst du ihn ja.
Aber irgendwie ist das jetzt eine gute Gelegenheit, mal etwas C ins Spiel zu bringen *Perl-Buch rauskram* *les* *etwas später*
Kannst du diese Perl-Buch nicht mal ratti leihen?
Auch hier lebt der Parent eindeutig weiter.
ist ja auch richtig.
Strange.
nur das verhalten von rattis Perl. Noch was komisches: Jörg Poßdeutscher schrieb:
Geguckt habe ich bisher in der perldoc unter perlipc und perlfork
unter perldoc finde ich weder perlfork noch perlipc kann es sein das ratti ein perl benutzt welches die emulation benutzt und deshalb diese Probleme hat? @ratti: wenn du einen testcode hat, der bei dir nicht läuft, poste ihn bitte hier, denn mit scheint das du ein verkonfiguriertes Perl hast. @Bernhard: kanst du mal nachgucken ob du bei dir "perlfork" in der perldoc findest? cu Gerald
On Mon, 29 Dec 2003 at 22:01 (+0100), Gerald Goebel wrote:
Bernhard Walle wrote:
Noch was komisches: Jörg Poßdeutscher schrieb:
Geguckt habe ich bisher in der perldoc unter perlipc und perlfork
unter perldoc finde ich weder perlfork noch perlipc
kann es sein das ratti ein perl benutzt welches die emulation benutzt und deshalb diese Probleme hat?
@ratti: wenn du einen testcode hat, der bei dir nicht läuft, poste ihn bitte hier, denn mit scheint das du ein verkonfiguriertes Perl hast.
@Bernhard: kanst du mal nachgucken ob du bei dir "perlfork" in der perldoc findest?
man perlfork [ratter, ratter] PERLFORK(1) Perl Programmers Reference Guide PERLFORK(1) NAME perlfork - Perl's fork() emulation [...] Gruß, Bernhard -- _________ http://www.bwalle.de _________________________________________________ Zivilcourage ist das, was von einem Menschen übrig bleibt, wenn der Vorgesetzte das Zimmer betritt. -- Wernher von Braun
Am Mo, den 29.12.2003 schrieb Gerald Goebel um 22:01:
Bernhard Walle wrote:
Aber irgendwie ist das jetzt eine gute Gelegenheit, mal etwas C ins Spiel zu bringen *Perl-Buch rauskram* *les* *etwas später*
Kannst du diese Perl-Buch nicht mal ratti leihen?
:-) Ich habe wahrlich Doku ohne Ende, das Netz ist voll, Bücher habe ich auch. Ich habe einen Denkfehler.
Noch was komisches: Jörg Poßdeutscher schrieb:
Geguckt habe ich bisher in der perldoc unter perlipc und perlfork
unter perldoc finde ich weder perlfork noch perlipc
perldoc ist der Befehl: # perldoc perlipc # perldoc perlfork ...oder online und ordentlich formatiert unter www.perldoc.com
kann es sein das ratti ein perl benutzt welches die emulation benutzt und deshalb diese Probleme hat?
@ratti: wenn du einen testcode hat, der bei dir nicht läuft, poste ihn bitte hier, denn mit scheint das du ein verkonfiguriertes Perl hast.
Glaube ich nicht. Code anbei. Was der Code tun SOLL ist: -forken -dissoziieren mit setsid Dann sollen beide Prozesse miteinander kommunizieren. Der (ehemalige, weil dissoziierte) Parent gibt durch einen gemeinsamen Socket den Befehl "DO", woraufhin das (ex-)Child mit einer 30%igen Wahrscheinlichkeit "abstürzt" - hier einfach mit der Meldung "e" (wie Error) exitet, um das zu simulieren. Später wird es natürlich eine echte Aktion ausführen und ggf. echt Segfaulten. Außerdem versteht Child den Befehl "DIE" (beende dich) und "HELLO" (Lebst du noch?) Wenn ja, antwortet es mit SMACK [Küßchen. Süß, ne?] ). Das "DO" wird 20 mal geschickt. Nach jedem "DO" überprüft Parent, ob Child noch "lebt", wenn nicht, soll ein neues Child gefork't werden. Zusammenfassend: Es sollten 20 "DO"'s ausgeführt werden, und einige davon würden eben "abstürzen" ('e' ausgeben), das Programm sollte durchlaufen. Aber, was wirklich passiert: Der erste "Absturz" gibt ein "e" aus (korrekt) und beendet dann sofort Child und Parent (Hä?). #!/usr/bin/perl -w use warnings; use strict; use Socket; use IO::Handle; use POSIX ":sys_wait_h"; use POSIX 'setsid'; # thousands of lines just for autoflush :-( # We say AF_UNIX because although *_LOCAL is the # POSIX 1003.1g form of the constant, many machines # still don't have it. my ($pid,$line); my ($kid,$parent); new_socket(); my $kid_pid = fork_kid(); if ( $parent ) { #parent my $alive; for ( my $i=0 ; ( $i<20 ) && ( $kid == 0) ; $i++) { $alive=kid_alive($kid_pid); if ($alive) { print CHILD "DO\n"; } else { new_socket(); $kid_pid=fork_kid(); } sleep 1; } # maybe we forked because kid died, # so "kid" can occur in parent process. # Get out here, go kid. if ( $parent ) { print "died as parent\n"; print CHILD "DIE\n"; waitpid($kid_pid,0); } if ( $kid ) { print "died as kid\n"; } } if ($kid) { #child print "kid runs\n"; while (1) { $line = <PARENT>; chomp $line; if ( $line eq "HELLO" ) { print PARENT "SMACK\n"; } if ( $line eq "DO" ) { if ( int(rand(100)) < 30 ) { die "e\n"; } } if ( $line eq "DIE" ) { close PARENT; exit; } } } sleep 4; sub fork_kid { $pid = fork; if ($pid != 0) { #parent close PARENT; $parent=-1; $kid=0; return $pid; } else { #kid die "cannot fork: $!" unless defined $pid; close CHILD; setsid or die "Can't start a new session: $!"; $parent=0; $kid=-1; return 0; } } sub kid_alive { my $pid=shift; if (! defined $pid ) { return 0; } # Undefined pid: Never forked before my $kid = waitpid( $pid , WNOHANG); if ( $kid == -1 ) { return 0; } # No such process # Found a(!) process. Is it the right one? print CHILD "HELLO\n"; chomp(my $line = <CHILD>); if ( $line eq "SMACK" ) { return -1; } # Kid's alive and replies return 0; # Uh. Rang the wrong door, or kid's dead. } sub new_socket { socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!"; CHILD->autoflush(1); PARENT->autoflush(1); } -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Hallo, [Alles mögliche gestrichen] Wie wäre es damit? Die wichtige Änderung ist hervorgehoben. #!/usr/bin/perl -w use warnings; use strict; use Socket; use IO::Handle; use POSIX ":sys_wait_h"; use POSIX 'setsid'; # thousands of lines just for autoflush :-( # We say AF_UNIX because although *_LOCAL is the # POSIX 1003.1g form of the constant, many machines # still don't have it. my ($pid,$line); my ($kid,$parent); new_socket(); my $kid_pid = fork_kid(); if ( $parent ) { #parent my $alive; for ( my $i=0 ; ( $i<20 ) && ( $kid == 0) ; $i++) { $alive=kid_alive($kid_pid); if ($alive) { print CHILD "DO\n"; } else { new_socket(); $kid_pid=fork_kid(); } sleep 1; print "$i\n"; #Mitzählen } # maybe we forked because kid died, # so "kid" can occur in parent process. # Get out here, go kid. if ( $parent ) { print "died as parent\n"; print CHILD "DIE\n"; waitpid($kid_pid,0); } if ( $kid ) { print "died as kid\n"; } } if ($kid) { #child print "kid runs\n"; srand; while (1) { $line = <PARENT>; chomp $line; if ( $line eq "HELLO" ) { print PARENT "SMACK\n"; } if ( $line eq "DO" ) { if ( int(rand(100)) < 30 ) { die "e\n"; } } if ( $line eq "DIE" ) { close PARENT; exit; } } } sleep 4; sub fork_kid { $pid = fork; if ($pid != 0) { #parent close PARENT; $parent=-1; $kid=0; return $pid; } else { #kid die "cannot fork: $!" unless defined $pid; close CHILD; setsid or die "Can't start a new session: $!"; $parent=0; $kid=-1; return 0; } } sub kid_alive { my $pid=shift; if (! defined $pid ) { return 0; } # Undefined pid: Never forked before my $kid = waitpid( $pid , WNOHANG); #Aenderung!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BEGIN print $kid."\n"; #Kann gestrichen werden #Bei mir war der Wert von $kid immer 0, wenn das Kind noch lebte if ( $kid != 0 ) { return 0; } #Aenderung!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ENDE # No such process # Found a(!) process. Is it the right one? print CHILD "HELLO\n"; chomp(my $line = <CHILD>); if ( $line eq "SMACK" ) { return 1; } # Kid's alive and replies return 0; # Uh. Rang the wrong door, or kid's dead. } sub new_socket { socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair: $!"; CHILD->autoflush(1); PARENT->autoflush(1); } Ich kann das allerdings nicht begründen. Das beruht nur auf der Tatsache, dass ich das so beobachtete und es funzt. Ferdinand
Moin, Am Mo, den 29.12.2003 schrieb Ferdinand Ihringer um 23:29:
Hallo,
[Alles mögliche gestrichen]
Wie wäre es damit? Die wichtige Änderung ist hervorgehoben.
Hunderttausend Höllenhunde! Du hast Recht! DANKE! DANKE! DANKE! DANKE! Ihr wart _alle_ ganz große Klasse. Die Liste ist 'ne Wucht. Und jetzt die Erklärung. Die Doku sagt: -------------------- waitpid PID,FLAGS Waits for a particular child process to terminate and returns the pid of the deceased process, or -1 if there is no such child process. On some systems, a value of 0 indicates that there are processes still running. -------------------- "Eigentlich" lässt man waitpid also auf einen Prozess los, der existiert, und der Befehl gibt dann, irgendwann, wenn dieser Prozess stirbt, dessen ID zurück. Solange wartet er. Sollte der Prozess gar nicht existieren, gibt er -1 zurück. Durch Angabe einer Flag lässt sich das Warten deaktivieren. Man kann also einfach mal gucken, ob der Prozess läuft, der Befehl "hängt" aber nicht bis zu dessen Ablegen. Ich habe mich auf das "-1" verlassen: "...if there is no such child process...", denn den gibt es zu dem Zeitpunkt ja gar nicht mehr. Es ist aber anscheinend so, daß trotzdem die ID zurückgereicht wird, was ich eigentlich bei einer Abfrage auf einen bereits verendeten Prozess komisch finde. There /is/ no such process. It died already! Damned. Hier hätte ich ganz klar -1 erwartet. Ein Doku-Bug? Dann würde ich den petzen. Oder seht ihr den Fehler bei mir? Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Moin,
* Joerg Rossdeutscher
Ich habe mich auf das "-1" verlassen: "...if there is no such child process...", denn den gibt es zu dem Zeitpunkt ja gar nicht mehr. Es ist aber anscheinend so, daß trotzdem die ID zurückgereicht wird, was ich eigentlich bei einer Abfrage auf einen bereits verendeten Prozess komisch finde. There /is/ no such process. It died already! Damned.
Hier hätte ich ganz klar -1 erwartet.
Lies mal die Manpage der C-Funktionen wait() oder waitpid, da steht's besser drin. Das Verhalten ist so auch sicherlich wünschenswert, da wait blockiert, solange das Kind nicht stirbt. Wenn Deine Interpretation richtig wäre, würdest Du in alle Ewigkeit warten, wenn das Kind bereits tot ist. (Oder ist das in Perl anders?) Thorsten -- The man who does not read good books has no advantage over the man who cannot read them. - Mark Twain
Moin, Am Di, den 30.12.2003 schrieb Thorsten Haude um 17:16:
* Joerg Rossdeutscher
[2003-12-30 15:39]: Ich habe mich auf das "-1" verlassen: "...if there is no such child process...", denn den gibt es zu dem Zeitpunkt ja gar nicht mehr. Es ist aber anscheinend so, daß trotzdem die ID zurückgereicht wird, was ich eigentlich bei einer Abfrage auf einen bereits verendeten Prozess komisch finde. There /is/ no such process. It died already! Damned.
Hier hätte ich ganz klar -1 erwartet.
Lies mal die Manpage der C-Funktionen wait() oder waitpid, da steht's besser drin.
Naja, für perl würde ich keine C manpages lesen, denn das ist ja gerne auch mal anders implementiert... In diesem Fall wäre es hilfreich gewesen. %-)
Das Verhalten ist so auch sicherlich wünschenswert, da wait blockiert, solange das Kind nicht stirbt. Wenn Deine Interpretation richtig wäre, würdest Du in alle Ewigkeit warten, wenn das Kind bereits tot ist.
(Oder ist das in Perl anders?)
In diesem Fall anders als du denkst. Du hast überlesen, daß man Options übergeben kann, was ich auch mache. Mit der Flag "NOHANG" kannst du einfach nur nachgucken, ob der Prozess weg ist, es wird aber nicht gewartet. Das führt (gewollt) dazu, daß waitpid ggf. bereits auf eine nicht mehr existierende ID angesetzt wird. perldoc definiert dafür laut Doku einen Rückgabewert von -1, was nicht stimmt. In Wirklichkeit ergibt waitpid auf eine gar nicht genutzte PID eben diese PID als Rückgabewert. Das geht auch in C: RETURN VALUE The process ID of the child which exited, or zero if WNOHANG was used and no child was available, or -1 on error (in which case errno is set to an appropriate value). Hier steht dann auch klar "-1 on error". Dagegen in perldoc "-1 if there is no such child process". Das sind ganz klar unterschiedliche Behauptungen. Ein terminiertes Child ist kein Error. Ohne das jetzt zu testen: -1 kommt wahrscheinlich, wenn ich auf negative, leere oder nicht-integer PIDs teste, oder sowas. In Wahrheit verhalten sich beide Sprachen gleich. Und zwar so, wie die C Doku behauptet. Seht ihr das auch so? Dann schicke ich das an perlbug@perl.org Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Hi ratti, hi Liste, Joerg Rossdeutscher wrote:
Ich habe mich auf das "-1" verlassen: "...if there is no such child process...", denn den gibt es zu dem Zeitpunkt ja gar nicht mehr. Es ist aber anscheinend so, daß trotzdem die ID zurückgereicht wird, was ich eigentlich bei einer Abfrage auf einen bereits verendeten Prozess komisch finde. There /is/ no such process. It died already! Damned.
Doch er existiert noch, er ist weder running, noch sleeping, sondern ein zombi. Er ist also mit der pid noch in der Prozesstabelle eingetragen. Die Zombies kommen genau aus diesem Grund vor, es wird ein Prozess angelegt, aber nicht abgefragt ob er schon beendet ist. Er verschwindet erst dann aus der Prozesstabelle, wenn auch der Parentprozess geschloßen wird, dann übernimt init und das fragt ab.
Hier hätte ich ganz klar -1 erwartet.
Erwartungen trügen manchmal.
Ein Doku-Bug? Dann würde ich den petzen. Oder seht ihr den Fehler bei mir?
1. Nein. 2. Ja. cu Gerald
Moin, Am Di, den 30.12.2003 schrieb Gerald Goebel um 20:19:
Joerg Rossdeutscher wrote:
Ich habe mich auf das "-1" verlassen: "...if there is no such child process...", denn den gibt es zu dem Zeitpunkt ja gar nicht mehr. Es ist aber anscheinend so, daß trotzdem die ID zurückgereicht wird, was ich eigentlich bei einer Abfrage auf einen bereits verendeten Prozess komisch finde. There /is/ no such process. It died already! Damned.
Doch er existiert noch, er ist weder running, noch sleeping, sondern ein zombi.
Wie kommst du da drauf? Er wurde sauber mit "exit" beendet. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Joerg Rossdeutscher wrote:
Moin,
Am Di, den 30.12.2003 schrieb Gerald Goebel um 20:19:
Joerg Rossdeutscher wrote:
Ich habe mich auf das "-1" verlassen: "...if there is no such child process...", denn den gibt es zu dem Zeitpunkt ja gar nicht mehr. Es ist aber anscheinend so, daß trotzdem die ID zurückgereicht wird, was ich eigentlich bei einer Abfrage auf einen bereits verendeten Prozess komisch finde. There /is/ no such process. It died already! Damned.
Doch er existiert noch, er ist weder running, noch sleeping, sondern ein zombi.
Wie kommst du da drauf? Er wurde sauber mit "exit" beendet.
Mit dem exit kannst du ja auch noch was zurückgeben, z. B. 0 für richtig ausgeführt, oder -1 für Fehler. An wen soll das denn gehen? Soll es einfach verschwinden? Die shell funktioniert doch genauso, geforkt wir da mit der eingabe des befehls, das WNOHANG machst du mit '&'. Und jedes mal wenn du dir Enter-Taste drückt fragt er wieder ab ob irgend eines seiner Kinder sich beendet hat, wen ja zeigt sie es am Bildschirm an. Also nochmal: Prozesse, die von einem Prozess erzeugt wurden, sich beendet haben und die nicht erwartet werden, werden zu Zombies, und stehen damit noch immer zur Abholung in der Prozess-Tabelle bereit. Es spielt also keine Rolle, ob sauber beendet wurde oder nicht. Es besteht ja auch die Möglichkeit, das der Prozess auf mehreren Wegen mit exit beendet wird, zum Beispiel weil etwas falsch gelaufen ist, dann möchtest du doch unter umständen wissen, ist der Prozess ganz durchgelaufen, oder ist irgendwo ein Fehler aufgetreten, während dein Parentprozess zwischenzeitlich etwas ganz anderes gemacht hat. Für dich könnte das eine Rolle spielen, bei den fontlingen. Wielange muß der Prozeß immer wieder neu angeschmissen werden, er stürzt vieleicht 1mal ab, 16 mal 100 mal, bei 2000 Schriften 10.000 Schriften. Wie willst du das steuern? Mit ner Zufallszahl, Counter? Nach dem waitpid dir die pid des Childprozesses zurückgegeben hat, steht ser return/exitcode in '#?', dh. du untersuchst den exitcode und entscheidest dann, was weiter geschehen soll. hth cu Gerald
Moin, Danke für deine Erklärungen. Ich bohren mal etwas nach: Am Mi, den 31.12.2003 schrieb Gerald Goebel um 00:10:
Joerg Rossdeutscher wrote:
Am Di, den 30.12.2003 schrieb Gerald Goebel um 20:19:
Joerg Rossdeutscher wrote:
komisch finde. There /is/ no such process. It died already! Damned.
Doch er existiert noch, er ist weder running, noch sleeping, sondern ein zombi.
Wie kommst du da drauf? Er wurde sauber mit "exit" beendet.
Mit dem exit kannst du ja auch noch was zurückgeben, z. B. 0 für richtig ausgeführt, oder -1 für Fehler. An wen soll das denn gehen?
Ich kann doch normalerweise jeden Prozess (solange er nicht innerhalb von Kernel-Routinen hängt) abschiessen. Wieso soll das hier anders sein?
Also nochmal: Prozesse, die von einem Prozess erzeugt wurden, sich beendet haben und die nicht erwartet werden, werden zu Zombies, und stehen damit noch immer zur Abholung in der Prozess-Tabelle bereit.
Es spielt also keine Rolle, ob sauber beendet wurde oder nicht.
Kannst du "Abholung" definieren? Und noch eine Verständnisfrage: 1. Ich dissoziiere den Prozess ja (setsid). Das sollte eigentlich (technisch) die Abhängigkeit zwischen den Prozessen beenden. Ich habe das noch nicht getestet, aber theoretisch sollte Child sogar weiterlaufen, wenn Parent beendet wird. 2. Nachdem das Programm durchgelaufen ist und auch ein paar mal geforkt hat, beendet es sich ordnungsgemäß. Ein anschliessendes "ps faux" zeigt keine Prozesse mehr. Dann ist doch alles in Ordnung, oder?
Es besteht ja auch die Möglichkeit, das der Prozess auf mehreren Wegen mit exit beendet wird, zum Beispiel weil etwas falsch gelaufen ist, dann möchtest du doch unter umständen wissen, ist der Prozess ganz durchgelaufen, oder ist irgendwo ein Fehler aufgetreten, während dein Parentprozess zwischenzeitlich etwas ganz anderes gemacht hat.
Für dich könnte das eine Rolle spielen, bei den fontlingen. Wielange muß der Prozeß immer wieder neu angeschmissen werden, er stürzt vieleicht 1mal ab, 16 mal 100 mal, bei 2000 Schriften 10.000 Schriften. Wie willst du das steuern? Mit ner Zufallszahl, Counter?
Das mit "Zufallszahl" verstehe ich jetzt nicht... Ich möchte, daß das Child Previews berechnet. Er bekommt Filenamen übergeben und generiert aus dem Font ein PNG. Entweder semmelt er dabei weg, dann wird der Font (weil kaputt) übersprungen und ein neues Child wird generiert. Oder aber es hat geklappt - dann darf der Prozess weiterleben und bekommt den nächsten Dateinamen. Wenn alle Fonts durch sind, bekommt Child ein Signal, sich normal zu beenden. Das das Child sich in diesem Test hier mittendrin gelegentlich selbst beendet, dient nur der Crash-Simulation. Sprich: Das Child wird genau so oft nachgestartet, wie es unerwartet abbricht. (Da sollten noch ein paar Sicherheitsabfragen rein, nach dem Motto "1000mal forken? Hier stimmt was nicht!" - aber jetzt mal ohne Sicherheitsdenke.)
Nach dem waitpid dir die pid des Childprozesses zurückgegeben hat, steht ser return/exitcode in '#?', dh. du untersuchst den exitcode und entscheidest dann, was weiter geschehen soll.
Der Exitcode ist gar nicht mal so interessant - die Tatsache eines "unbefohlenen Beendens" sagt eigentlich schon alles. (Im RealLife dann doch wieder, weil z.B. die Platte voll sein könnte oder so - lassen wir das hier mal aussen vor). Steh ich auf'm Denkschlauch? Ich sehe einfach kein Problem mehr. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
An Alle ein frohes und erfolgreiches neues Jahr, Joerg Rossdeutscher wrote:
Danke für deine Erklärungen. Ich bohren mal etwas nach:
PPS: War gut, habe selber wieder einiges Aufgefrischt, intensiviert.
Am Mi, den 31.12.2003 schrieb Gerald Goebel um 00:10:
Mit dem exit kannst du ja auch noch was zurückgeben, z. B. 0 für richtig ausgeführt, oder -1 für Fehler. An wen soll das denn gehen?
Ich kann doch normalerweise jeden Prozess (solange er nicht innerhalb von Kernel-Routinen hängt) abschiessen. Wieso soll das hier anders sein?
Es ist nicht anders, der Prozess wird ja auch abgesch0ssen, aber in der Prozessrabelle, bleibt er noch stehen, er lebt also in der Prozesstabelle noch weiter obwohl er tot ist, daher auch der Name: Zombie, lebender Toter. Jetzt ist natürlich die Frage: Welchen Rückgabewert hat er dann? Auch das ist eindeutig geregelt: Da der Kernel keinen Rückgabewert findet, setzt er dafür das Signal ein, mit dem der Prozess abgeschoßen wurde. Für C, gibt es dafür Makros um den Wert auszulesen, ist irgendwas mit AFAIK Bitverschiebung. Damit kannst du denn genau sagen warum der Prozess beendet wurde.
Also nochmal: Prozesse, die von einem Prozess erzeugt wurden, sich beendet haben und die nicht erwartet werden, werden zu Zombies, und stehen damit noch immer zur Abholung in der Prozess-Tabelle bereit.
Es spielt also keine Rolle, ob sauber beendet wurde oder nicht.
Kannst du "Abholung" definieren?
Mit "Abholung" meine ich hier, das der Rückgabewert (der immer vorhanden ist) für die pid aus der Prozesstabelle mit einem wait-Befehl (es gibt mehrere) abgerufen wird. Naormalerweise sollte das der Parentprozess machen, wenn er nicht mehr existiert, macht das Prozess-No. 1 (init). BTW: Sollte ich gesagt haben Prozess-No. 1 (init) hat keinen Parentprozess, so ist das falsch, beim erneuten Durchsichten meiner Skripte, fand ich, daß nur der Prozess mit der No. 0 kein Parentprozess hat. Prozess-No. 0 ist der boot-prozess. ps -C init --format "%p %P %c" PID PPID COMMAND 1 0 init
Und noch eine Verständnisfrage:
1. Ich dissoziiere den Prozess ja (setsid). Das sollte eigentlich (technisch) die Abhängigkeit zwischen den Prozessen beenden. Ich habe das noch nicht getestet, aber theoretisch sollte Child sogar weiterlaufen, wenn Parent beendet wird.
Was verstehst du unter "dissoziiere", bitte Definition. Ich glaube, du verwechselst hier 2 Sachen: Mit setsid, eröffnest du eine neue Session, und machst den aktuellen Prozess zum Sessionleader dieser Session. Man muß aber folgende 3 Sachen getrennt betrachten: 1. Prozesse 2. Prozessgruppen 3. Sessions Also fangen wir mal bei 3 an, was ist eine Session? Wenn du dich einloggst, eröffnest du damit einen neue Session, mit der shell als Session-Leader. Wenn du dich ausloggst, schließt du diese Session. Wie du siehst kann eine Session Prozessgruppen und Prozesse enthalten. Was geschieht also bei einer Session, Interessant ist das Schließen der Session, denn sonst verhält sie sich wie ein normaler Prozess, dh. du kannst mit ihr alles machen was du mit einem normalen Prozess auch machen kannst, der einzige unterschied ist, das sie noch zusätzlich die Funktion des Session-Leaders inne hat. Also was macht der Session-Leader wenn er beendet wird? Er schickt an alle Prozesse, die in der Session sind ein Signal, das sie sich zu beenden haben, das ist das Signal, das er selber auch bekommen hat. Dann scheckt er ob sich seine Prozesse beendet haben, wenn nicht, nimmt er das nächst härtere Signal, bis zum kill. Über dieses Phänomen haben wir uns alle mit Sicherheit schon mal geärgert, einen lang laufenden Prozess in den Hintergrund geschickt, und dann ausgeloggt, um beim nächsten einloggen festzustellen, daß, der Hintergrundprozess nicht bis zum Enden gearbeitet hat. Um genau das zu machen, dafür gibt es den Befehl "nohup", er macht folgendes: er forkt sich, macht den neuen Prozess zu einem neuen Session-Leader, und überlagert dann den Prozess mit dem Code des Programms, das man angegeben hat. Es ist damit von der alten Session unabhängig, wird also nicht beendet, wenn diese beendet wird. Einen Session ohne Session-Leader gibt es nicht, wird der Session-Leader beendet, verschwindet auch die Session und damit alls ihre Prozesse. Was ist eine Prozessgruppe? Jeder Prozess gehört auch zu einer Prozessgruppe, normalererweise zu der Prozessgruppe, zu der auch der Parentprozess gehört. Auch eine Prozessgruppe hat einen Group-Leader. Aber sie muß keinen haben, dh. sie kann den Prozess, der Group-Leader ist überleben. Vezwickt? Aber es kommt noch besser: Was ist die Aufgabe des Group-Leaders? Sie ist ja noch nichtmal, das er dasein muß. Also schicke ich dem Prozess, der Group-Leader ist, ein Signal z.B. mit kill, so beendet er sich, die Prozessgruppe bleibt aber weiter bestehen, und seine Childs, werden Prozess-No. 1 (init) untergeschoben. Also warum gibt es einen Group-Leader? Bekommt der Group-Leader ein Signal durch Benutzer-Eingriff (Strg-C etc.) gibt er dieses Signal an alle Prozesse der Prozessgruppe weiter. Das ist die einzige Aufgabe des Group-Leaders. Was ist ein Prozess? Einfach gesagt unter Linux: Alles. Was Kennzeichnet aber einen Prozess? Hauptsächlich 4 Dinge: 1. Er ist eindeutig zu identifizieren: pid 2. Er hat einen Parent: ppid 3. Er gehört einen Prozessgruppe an: pgid 4. Er gehört einer Session an: sid Beim beenden, schickt der Prozess seinem Parent ein Signal (SIGCHLD, No.: 17), das ist das Signal, auf das wait reagiert/wartet. Die resourcen des Child sind zu dem Zeitpunkt schon freigegeben und der Returncode steht in der Prozesstabelle. Dort kann er nun Abgeholt werden, das macht Normal der Parent, muß er aber nicht. Solange der Prozess noch in der Prozesstabelle steht, ist er ein "Zombi" oder auch defunct (unfunktional). Stirbt jetzt der Parent, geht Child an "Init" ... Man kann auch ein Programm schreiben, welches nachschaut welche pids von Zombies sind, und dann mit wait die entsprechenden pids abruft, auch so kann man Zombies entfernen, über Sinn oder Unsinn eines solchen Programms kann man streiten. Was passiert aber wenn ein Prozess "abnormal" beendet wird, auch dann entsteht gibt es ein SIGCHLD, nur was ist der Returncode? Der einzige der das beantworten kann ist der Kernel. Er weiß welches Signal an den Prozess geschickt wurde, und findet im Returncode des Prozesses nichts, so setzt er als Returncode das Signal ein. Schick ich dem Prozess mit kill ein Signal wird dieses als Returncode benutzt, das ist auch der einzige Unterschied zwischen Signalen die ich schicke (z. B. SIGSEGV) und einem vom Kernel erzeugtem, der Kernel weiß nichts davon. Literatur-Quellen: diverse Uralt Linuxbücher, Howtos etc. überall steht ein bischen drin, und: "Betriebssysteme und betriebssystemnahe Programmierung" Autor: Axel Rogat der Integrierten Arbeitsgruppe mathematische Probleme aus dem Ingenieurbereich Fachbereiche Mathematik, Bergische Universität Gesamthochschule - Wuppertal Februar 2000
2. Nachdem das Programm durchgelaufen ist und auch ein paar mal geforkt hat, beendet es sich ordnungsgemäß. Ein anschliessendes "ps faux" zeigt keine Prozesse mehr. Dann ist doch alles in Ordnung, oder?
Ja.
Für dich könnte das eine Rolle spielen, bei den fontlingen. Wielange muß der Prozeß immer wieder neu angeschmissen werden, er stürzt vieleicht 1mal ab, 16 mal 100 mal, bei 2000 Schriften 10.000 Schriften. Wie willst du das steuern? Mit ner Zufallszahl, Counter?
Das mit "Zufallszahl" verstehe ich jetzt nicht...
War ein Witz!
Steh ich auf'm Denkschlauch? Ich sehe einfach kein Problem mehr.
Ich auch nicht, wenn du weißt, was du machst, die Frage ist nur, brauchst du "setsid"? hth cu Gerald PS.: Sorry, für die Länge und sie teilweisen Wiederholungen.
Moin, Am Do, den 01.01.2004 schrieb Gerald Goebel um 23:58:
An Alle ein frohes und erfolgreiches neues Jahr,
Dir auch. Gerald, vielen Dank für den Text. Von den meisten Sachen wußte ich gar nicht, daß es sie überhaupt gibt. Mann, ist das verzwickt. :-)
Joerg Rossdeutscher wrote:
Am Mi, den 31.12.2003 schrieb Gerald Goebel um 00:10:
Mit dem exit kannst du ja auch noch was zurückgeben, z. B. 0 für richtig ausgeführt, oder -1 für Fehler. An wen soll das denn gehen?
Ich kann doch normalerweise jeden Prozess (solange er nicht innerhalb von Kernel-Routinen hängt) abschiessen. Wieso soll das hier anders sein?
Es ist nicht anders, der Prozess wird ja auch abgesch0ssen, aber in der Prozessrabelle, bleibt er noch stehen, er lebt also in der Prozesstabelle noch weiter obwohl er tot ist, daher auch der Name: Zombie, lebender Toter.
OK, verstehe. Das hiesse, der Prozess bleibt unter "ps" so lange zu sehen, bis mein Parent "waitpid" ausführt? ...und da ich das ja auch mache, ist er bei mir eben nicht mehr in "ps" zu sehen.
Jetzt ist natürlich die Frage: Welchen Rückgabewert hat er dann? Auch das ist eindeutig geregelt: Da der Kernel keinen Rückgabewert findet, setzt er dafür das Signal ein, mit dem der Prozess abgeschoßen wurde. Für C, gibt es dafür Makros um den Wert auszulesen, ist irgendwas mit AFAIK Bitverschiebung. Damit kannst du denn genau sagen warum der Prozess beendet wurde.
Ja, irgendwas mit Bit 7 wegtun und den Rest rotieren... ich glaube, das habe ich schonmal benutzt.
Und noch eine Verständnisfrage:
1. Ich dissoziiere den Prozess ja (setsid). Das sollte eigentlich (technisch) die Abhängigkeit zwischen den Prozessen beenden. Ich habe das noch nicht getestet, aber theoretisch sollte Child sogar weiterlaufen, wenn Parent beendet wird.
Was verstehst du unter "dissoziiere", bitte Definition.
Ich habe in der Perl-Doku gelesen, wenn man einen Prozess dissoziiert, dann würde er zum Daemon und er wird auch dann nicht beendet, wenn sein Parent nicht beendet. Das hatte ich beabsichtigt. Ah ja, hier: http://www.perldoc.com/perl5.8.0/pod/perlipc.html unter: Complete Dissociation of Child from Parent ...und da steht auch was von "process group leader", was ich früher nicht verstanden hatte. Meine Güte, ich war jung und dumm, jedenfalls gestern.
1. Prozesse 2. Prozessgruppen 3. Sessions
[Erklärungen] Danke!
Für dich könnte das eine Rolle spielen, bei den fontlingen. Wielange muß der Prozeß immer wieder neu angeschmissen werden, er stürzt vieleicht 1mal ab, 16 mal 100 mal, bei 2000 Schriften 10.000 Schriften. Wie willst du das steuern? Mit ner Zufallszahl, Counter?
Das mit "Zufallszahl" verstehe ich jetzt nicht...
War ein Witz!
So isser, der Rheinländer. Wenn er 'ne Kiste sieht, muß er draufsteigen und 'ne Rede halten, die gar nicht komisch ist. :-)))))))))
Steh ich auf'm Denkschlauch? Ich sehe einfach kein Problem mehr.
Ich auch nicht, wenn du weißt, was du machst, die Frage ist nur, brauchst du "setsid"?
Ich hatte die Hoffnung, irgendwann mal an den Punkt zu kommen, wo das Child als Daemon im Hintergrund bleibt und nicht nur für seinen Parent, sondern für alle anderen Skripte als "Preview-Server-Daemon" zur Verfügung steht. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Am Freitag, 2. Januar 2004 12:58 schrieb Joerg Rossdeutscher:
Am Do, den 01.01.2004 schrieb Gerald Goebel um 23:58: [...]
Jetzt ist natürlich die Frage: Welchen Rückgabewert hat er dann? Auch das ist eindeutig geregelt: Da der Kernel keinen Rückgabewert findet, setzt er dafür das Signal ein, mit dem der Prozess abgeschoßen wurde. Für C, gibt es dafür Makros um den Wert auszulesen, ist irgendwas mit AFAIK Bitverschiebung. Damit kannst du denn genau sagen warum der Prozess beendet wurde.
Ja, irgendwas mit Bit 7 wegtun und den Rest rotieren... ich glaube, das habe ich schonmal benutzt. [...]
WIFEXITED(status) WEXITSTATUS(status) WIFSIGNALED(status) ... man waitpid Dann brauchst Du Dich nicht selbst um die Bitmasken zu kümmern. Jan
hi ratti, hi Liste, Joerg Rossdeutscher wrote:
Am Mo, den 29.12.2003 schrieb Gerald Goebel um 22:01:
Bernhard Walle wrote:
Aber irgendwie ist das jetzt eine gute Gelegenheit, mal etwas C ins Spiel zu bringen *Perl-Buch rauskram* *les* *etwas später*
Kannst du diese Perl-Buch nicht mal ratti leihen?
:-) Ich habe wahrlich Doku ohne Ende, das Netz ist voll, Bücher habe ich auch. Ich habe einen Denkfehler.
Glaub ich dir ich meinte aber dieses Perl-Buch: Perl-Buch lesen, und C programmieren ;-)
perldoc ist der Befehl: # perldoc perlipc # perldoc perlfork
...oder online und ordentlich formatiert unter www.perldoc.com
Habe die ganze Zeit "perldoc -f perlfork" versucht, mit "perldoc perlfork" finde ich es auch.
kann es sein das ratti ein perl benutzt welches die emulation benutzt und deshalb diese Probleme hat?
@ratti: wenn du einen testcode hat, der bei dir nicht läuft, poste ihn bitte hier, denn mit scheint das du ein verkonfiguriertes Perl hast.
Glaube ich nicht.
stimmt, dein Code funktionierte bei mir auch nicht.
Code anbei. Was der Code tun SOLL ist:
Das war gut, beachte Zeitform im letzten Satz von mir.
Aber, was wirklich passiert: Der erste "Absturz" gibt ein "e" aus (korrekt) und beendet dann sofort Child und Parent (Hä?).
Deine kid_alive ist das problem:
sub kid_alive { my $pid=shift; if (! defined $pid ) { return 0; } # Undefined pid: Never forked before
my $kid = waitpid( $pid , WNOHANG);
solang der kid läuft gibt waitpid 0 zurück. ist kid aber beendet, gibt waitpid die pid des beendeten kid zurück.
if ( $kid == -1 ) { return 0; } # No such process
bis hierher noch kein problem.
# Found a(!) process. Is it the right one?
aber hier: ob kid noch läuft oder nicht, er versucht zu schreiben und zu lesen.
print CHILD "HELLO\n"; chomp(my $line = <CHILD>); if ( $line eq "SMACK" ) { return -1; } # Kid's alive and replies
return 0; # Uh. Rang the wrong door, or kid's dead. } benutzte mal diesen code:
sub kid_alive { my $pid=shift; if (! defined $pid ) { return 0; } # Undefined pid: Never forked before my $kid = waitpid( $pid , WNOHANG); if ($kid == 0 ){ print CHILD "HELLO\n"; chomp(my $line = <CHILD>); if ( $line eq "SMACK" ) { return -1; } # Kid's alive and replies } return 0; } hth cu Gerald
Hallo, Am Dienstag, 30. Dezember 2003 00:10 schrieb Gerald Goebel:
solang der kid läuft gibt waitpid 0 zurück. ist kid aber beendet, gibt waitpid die pid des beendeten kid zurück.
In perldoc -f waitpid steht bei am Anfang das: waitpid PID,FLAGS Waits for a particular child process to terminate and returns the pid of the deceased process, or "-1" if there is no such child process. On some systems, a value of 0 indicates that there are processes still running. Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ? Oder geben andere Systeme dann trotzdem einen Wert zurück und es würde auch ein Fehler im Programm sein? Oder wie müsste man das dann formulieren? Oder ist es zu schwer so ein System anzutreffen, als dass es sich lohnen würde? Ferdinand
Am Dienstag, 30. Dezember 2003 00:36 schrieb Ferdinand Ihringer:
Hallo,
Am Dienstag, 30. Dezember 2003 00:10 schrieb Gerald Goebel:
solang der kid läuft gibt waitpid 0 zurück. ist kid aber beendet, gibt waitpid die pid des beendeten kid zurück.
In perldoc -f waitpid steht bei am Anfang das: waitpid PID,FLAGS Waits for a particular child process to terminate and returns the pid of the deceased process, or "-1" if there is no such child process. On some systems, a value of 0 indicates that there are processes still running.
Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ?
Äh. Natürlich meine ich "unless ($kid > 0 and $kid < 0)". Sonst wäre die Bedingung ja immer wahr.
Moin,
* Ferdinand Ihringer
Am Dienstag, 30. Dezember 2003 00:36 schrieb Ferdinand Ihringer:
Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ?
Äh. Natürlich meine ich "unless ($kid > 0 and $kid < 0)". Sonst wäre die Bedingung ja immer wahr.
Na super, so ist sie immer falsch. Thorsten -- There must be a parallel universe where Starbucks sells cocaine in dilute, controlled, taxed doses, but where (crack) caffiene is sniffed and smoked in huge binges, and smuggled in by evil Columbian cartels. - Rogerborg
Am Dienstag, 30. Dezember 2003 01:24 schrieb Thorsten Haude:
Moin,
* Ferdinand Ihringer
[2003-12-30 01:06]: Am Dienstag, 30. Dezember 2003 00:36 schrieb Ferdinand Ihringer:
Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ?
Äh. Natürlich meine ich "unless ($kid > 0 and $kid < 0)". Sonst wäre die Bedingung ja immer wahr.
Na super, so ist sie immer falsch.
Nein, nicht wenn $kid gleich 0 oder keine Zahl ist. Oder bin ich schon so müde, dass ich grade nur Schwachsinn schreibe? Ferdinand
Am Dienstag, 30. Dezember 2003 01:26 schrieb Ferdinand Ihringer:
Am Dienstag, 30. Dezember 2003 01:24 schrieb Thorsten Haude:
Moin,
* Ferdinand Ihringer
[2003-12-30 01:06]: Am Dienstag, 30. Dezember 2003 00:36 schrieb Ferdinand Ihringer:
Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ?
Äh. Natürlich meine ich "unless ($kid > 0 and $kid < 0)". Sonst wäre die Bedingung ja immer wahr.
Na super, so ist sie immer falsch.
Nein, nicht wenn $kid gleich 0 oder keine Zahl ist. Oder bin ich schon so müde, dass ich grade nur Schwachsinn schreibe?
Gut, ich bin so müde. Ihr wisst jedenfalls, was ich meinte, und das hat sich jetzt ja erledigt. Ferdinand
Moin,
* Ferdinand Ihringer
Am Dienstag, 30. Dezember 2003 01:24 schrieb Thorsten Haude:
* Ferdinand Ihringer
[2003-12-30 01:06]: Am Dienstag, 30. Dezember 2003 00:36 schrieb Ferdinand Ihringer:
Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ?
Äh. Natürlich meine ich "unless ($kid > 0 and $kid < 0)". Sonst wäre die Bedingung ja immer wahr.
Na super, so ist sie immer falsch.
Nein, nicht wenn $kid gleich 0 oder keine Zahl ist.
Wenn $kid == 0, dann ist es weder größer noch kleiner 0, also sicher auch nicht beides. Wenn es keine Zahl ist, dann ist es entweder ein Syntaxfehler oder wird eben doch als Zahl interpretiert.
Oder bin ich schon so müde, dass ich grade nur Schwachsinn schreibe?
Gute Nacht! Thorsten -- Linux is user-friendly. But it is neither ignorant-friendly nor idiot-friendly.
Hi Ferdinand, hi Liste, Ferdinand Ihringer wrote:
Am Dienstag, 30. Dezember 2003 00:10 schrieb Gerald Goebel:
solang der kid läuft gibt waitpid 0 zurück. ist kid aber beendet, gibt waitpid die pid des beendeten kid zurück.
In perldoc -f waitpid steht bei am Anfang das: waitpid PID,FLAGS Waits for a particular child process to terminate and returns the pid of the deceased process, or "-1" if there is no such child process. On some systems, a value of 0 indicates that there are processes still running.
Da steht "on some systems". Wäre dann nicht "unless ($kid > 0 or $kid < 0)" besser als "if ($kid == 0)" ?
waitpid heißt waitpid, weil es auf die Beendigung des des angegebenen Prozess oder eines Prozesses der angegebenen Prozessgruppr wartet, der Rückgabewert ist die pid des beendeten prozesses, wichtig wenn auf Prozessgruppen gewartet wird. Ist nichts da auf was er warten kann, schlägt der Befehl fehl und gibt -1 zurück. Das ist der Normalfall. Jetzt gibt es noch die Möglichkeit, über die flags, zusagen warte nicht. Genau das wird hier benutzt (WNOHANG), dann muß waitpid 0 zurückgeben, wenn der Prozess noch läuft, bei Prozessgruppen, wenn kein Prozess beendet wurde. Das "on some systems" vermute ich mal bezieht sich darauf das es OS gibt wo er nicht wartet, also WNOHANG standard ist, er also immer 0 zurückgibt und dann weiterläuft. cu Gerald
Hallo, Danke erstmal für deine lange Mail. Am Mo, den 29.12.2003 schrieb Gerald Goebel um 16:51:
_Multiprocessing:_ Das erstellen eines neuen Prozesses mit fork, der vollkommen unabhängig vom Parentprozess ist. Die einzige Kommunikation zum Parentprozess besteht über einen Returncode, der mit wait vom Parentprozess abgefragt werden kann/muß. Stirbt der Parentprozess, fängt init (Prozess# 1) den Childprozess auf, und der Childprozess wird damit zu einem Deamon. Alles an Variablen, Filedescriptoren etc. sind im Childprozess unabhängig und seperat vorhanden.
_Multithreading:_ Das erstellen eiens neuen Threads mit einem in der Prog.-sprache dafür vorgesehenen Befehls, er ist nicht unabhängig, und teilt sich alle "Variablen", Filedescriptoren etc. mit den anderen Threads.
Hier scheint sich genau der Nachteil vom Multithreding bemerkbar zu machen.
Meine Vermutung ist, der Befehl fork in Perl startet nicht einen eigenen Prozess, sondern macht nur einen eigenen Tread im Interpreter dafür auf. Neben dem Verhalten sprechen noch einige andere Aussagen dafür:
fork dupliziert den Thread und seinen Speicher. Damit teilen beide zwar die gleichen offenen Files, Variablen sind aber unabhängig voneinander. Der von mir gepostete Code ist "von sauberer Programmierung befreit" :-), prinzipiell sollte man aus obigem Grund z.B. STDOUT nach dem fork'en schliessen und neu öffnen, damit beide Prozesse schreiben können. Außerdem disoziiere ich den Child-Prozess. Damit sollte er eigentlich eigenständig werden und "dämonisieren". Was auch der Sinn der Sache ist. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Joerg Rossdeutscher wrote:
fork dupliziert den Thread und seinen Speicher. Damit teilen beide zwar
fork erzeugt normal einen neuen Prozess, keinen Thread.
die gleichen offenen Files, Variablen sind aber unabhängig voneinander.
Das heißt, alle Variablen sind Threadsafe? Warum benutze ich dann threads und nicht gleich eigene Prozesse?
Der von mir gepostete Code ist "von sauberer Programmierung befreit" :-), prinzipiell sollte man aus obigem Grund z.B. STDOUT nach dem fork'en schliessen und neu öffnen, damit beide Prozesse schreiben können.
Außerdem disoziiere ich den Child-Prozess. Damit sollte er eigentlich eigenständig werden und "dämonisieren". Was auch der Sinn der Sache ist.
Das hast du ausprobiert? der Child läuft unter ppid == 1? Ich bin mir jetzt zu 99% sicher, das du mit einem Perl arbeitest, welches nicht das nativ fork() benutzt, sondern diese fork-emulation. cu Gerald
Moin, Am Mo, den 29.12.2003 schrieb Gerald Goebel um 22:27:
Joerg Rossdeutscher wrote:
fork dupliziert den Thread und seinen Speicher. Damit teilen beide zwar
fork erzeugt normal einen neuen Prozess, keinen Thread.
OK.
die gleichen offenen Files, Variablen sind aber unabhängig voneinander.
Das heißt, alle Variablen sind Threadsafe? Warum benutze ich dann threads und nicht gleich eigene Prozesse?
Da komme ich jetzt mit meinem Wissen nicht mit. "Das Ding" (Prozess, task, thread,...?) wird im Speicher dupliziert. Die Variablen sind, wie in zwei verschiedenen Programmen, völlig unabhängig voneinander. Beide "Dinger" teilen sich aber das gleiche Environment, da das ebenfalls dupliziert wurde, also offene Dateien.
Außerdem disoziiere ich den Child-Prozess. Damit sollte er eigentlich eigenständig werden und "dämonisieren". Was auch der Sinn der Sache ist.
Das hast du ausprobiert? der Child läuft unter ppid == 1?
ppid? Du meinst die Prozess-ID? Die scheint sich durch setsid nicht zu ändern. Die ausgabe der PID, in perl mit "print $$", ergibt für Child einen um 1 größeren Wert als für Parent, zum Beispiel 1000 und 1001.
Ich bin mir jetzt zu 99% sicher, das du mit einem Perl arbeitest, welches nicht das nativ fork() benutzt, sondern diese fork-emulation.
Die sollte eigentlich nur unter Windows laufen: --- Perl provides a fork() keyword that corresponds to the Unix system call of the same name. On most Unix‐like platforms where the fork() system call is available, Perl’s fork() simply calls it. --- GRuß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Joerg Rossdeutscher wrote:
Am Mo, den 29.12.2003 schrieb Gerald Goebel um 22:27:
Das heißt, alle Variablen sind Threadsafe? Warum benutze ich dann threads und nicht gleich eigene Prozesse?
Da komme ich jetzt mit meinem Wissen nicht mit. "Das Ding" (Prozess, task, thread,...?) wird im Speicher dupliziert. Die Variablen sind, wie in zwei verschiedenen Programmen, völlig unabhängig voneinander. Beide "Dinger" teilen sich aber das gleiche Environment, da das ebenfalls dupliziert wurde, also offene Dateien.
Was du beschreibst ist für seperate Prozesse richtig. Mich verwirrte nur weil du von Threads sprachst. Bei Threads, wird eben nicht alles dupliziert, sondern nur die Variablen, die als Thread-Variablen gekenzeichnet sind. Diese Variablen werden in jedem Thread seperat gehalten, die anderen nicht, auf die kannst du von jedem thread zugreifen, verändern etc. das heißt du brauchst dich um die Komunikation nicht zu kümmern. variable1 = 1 in thread1: solange variable1 < 3 ist wenn variable1 =1 ist mach dies wenn variable1 =2 ist mach das in thread2: zähle von 1 bis 1.000.000 dann setzte variable1 auf 2 und zähle bis 2.000.000 weiter dann setzte variable1 auf 3. beide threads laufen parallel. thread1 läuft genau solange bis thread2 auf 2.000.000 gezählt hat und er das nächstmal die variable1 abfragt, (thread2 bis 1.000.000) -> thread1 macht dies (thread2 bis 2.000.000) -> thread1 macht das Wenn du diese mit Prozessen machen willst, mußt du die ganze Kommunikation selber programmieren. Allerdings, schmiert thread2 ab, reißt er den ganzen Prozess mit (es seiden man fängts ab). Im extremfall bleibt dann auch schon mal ein ganzes OS stehen.
ppid? Du meinst die Prozess-ID?
Nope, ppid = ParentProzessID; ProzessID = pid.
Ich bin mir jetzt zu 99% sicher, das du mit einem Perl arbeitest, welches nicht das nativ fork() benutzt, sondern diese fork-emulation.
Die sollte eigentlich nur unter Windows laufen:
Richtig, ich sagte ja 99%, was 1% doch ausmachen kann. Siehe andere Mail von mir. cu Gerald
Hallo Gerald, hallo Ratti, hallo Leute, Am Montag, 29. Dezember 2003 16:51 schrieb Gerald Goebel:
_Multiprocessing:_ [...] _Vorteil:_ extrem robust
Also genau das, was wir brauchen ;-)
_Nachteil:_ Alle Komunikation zwischen Parent- und ChildProzess muß seperat über sharedmemory, semaphoren oder pipes programmiert werden.
Tja, Pipes sind da wohl die schmerzloseste (und vermutlich auch sicherste) Variante. Bei shared memory hätte ich Bedenken, dass ein wildgewordener Kindprozess irgendwas falsches hinterlässt. (wobei ich von shared memory fast keine Ahnung habe, hört sich aber gefährlich an ;-) semaphoren sagt mir nix, muss ich das (als Perl-Anfänger) kennen oder gibt es das bei Perl gar nicht? Ratti, da fällt mir gerade wieder eine Mail von David in fontlinge-devel ein, in der er auf man IPC::Open3 man IPC::Open2 verwiesen hat. Könnte einen Versuch wert sein. Allerdings stimmt micht die Aussage "you could block forever" (falls man auf den Text der Pipe wartet, aber nix auftaucht), doch etwas bedenklich. Aber: sollte zu schaffen sein - IPC::Open2 verwenden, STDERR auf STDOUT umleiten (2>&1) und im Fehlerfall beim Abfangen eines Segfault eine Meldung ausgeben. Kannst Du ja testen, indem Dein "Kind"-Prozess einfach mal nix ausgibt und sich verabschiedet... Wenn nichts anderes hilft, rufen wir eben "fontlinge_worker ; echo ERROR" auf ;-)
[...] Siehe auch: http://www.gsp.com/cgi-bin/man.cgi?section=1&topic=perlfork <Zitate>
Oder man perlfork für alle, die keine Flat haben ;-) Gruß Christian Boltz --
Ooooch, nu sei doch nicht gleich gnidderig. :-) Bin ich doch gar nicht :-))) Dann ist ja gut. (Bratpfanne unauffällig fallenlass und mit dem Fuß wegstubs...) [> Christian Boltz und Ratti in fontlinge-devel]
Moin,
* Gerald Goebel
Meine Vermutung ist, der Befehl fork in Perl startet nicht einen eigenen Prozess, sondern macht nur einen eigenen Tread im Interpreter dafür auf. Neben dem Verhalten sprechen noch einige andere Aussagen dafür:
Habt mir alle gekillfilet oder wollt ihr lieber noch rumraten, bevor Euch jemand die Lösung verrät? Rattis Programm beendet sich mit einem SIGPIPE, weil der Parent in eine Pipe schreibt, die keinen Leser mehr hat. Ist jedenfalls meine Theorie, nachvollziehbar gemacht in meiner ersten Mail. Thorsten -- There are 10 types of people in the world: Those who understand binary, and those who don't.
Hallo, Am Di, den 30.12.2003 schrieb Thorsten Haude um 00:46:
Habt mir alle gekillfilet
Weder gekillt noch filetiert. :-)
oder wollt ihr lieber noch rumraten, bevor Euch jemand die Lösung verrät? Rattis Programm beendet sich mit einem SIGPIPE, weil der Parent in eine Pipe schreibt, die keinen Leser mehr hat. Ist jedenfalls meine Theorie, nachvollziehbar gemacht in meiner ersten Mail.
Das ist Recht, aber das war ein Folgefehler. Da hätte ein "Leser", also Child, sein müssen. An der Stelle habe ich nicht geschaltet. Ich war so fokussiert auf das vermutete Problem "Child killt parent", daß ich die eigentliche Ursache "Abfrage falsch, daher kein Nachstart eines (benötigten) neuen Childs durch Parent" übersehen habe. Auch dir vielen Dank. Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
Moin,
* Joerg Rossdeutscher
Soweit die Theorie. In der Praxis funktioniert das prima, bis tatsächlich ein Fehler im Child-Block auftritt. Derzeit simuliere ich das einfach über ein "die" mit 30%-Chance. Es scheint, als würde ein "die" im Child auch den Parent sofort beenden. Verstehe ich nicht. Steht in der Doku anders.
- - - Schnipp - - - yooden@eumel % ./ratti.pl ~/tmp e 141 yooden@eumel % let a=141-128 && echo $a ~/tmp 13 yooden@eumel % man 7 signal | grep 13 ~/tmp SIGPIPE 13 A Broken pipe: write to pipe with no readers - - - Schnapp - - - - Das "e" in der zweiten Zeile verstehe ich nicht, vermutlich ebenfalls ein Problem mit der Spülung. Ich empfehle use English; $EXTREME_AUTOFLUSHING = 1; oder so ähnlich, ich weiß gerade nicht, wie die Variable heißt. - Die 141 in Zeile 3 ist $? des Vorprozesses (erscheint nur wenn != 0), also Dein Problem. (Zsh ruled übrigens.) Eine Lösung kann sein, eben doch ein Signal auszuwerten, aber SIGCHLD oder SIGPIPE. Dann unterläßt Du entweder das Schreiben in die Pipe, wenn das Kind im Jenseits ist oder nimmst nach dem Schreiben zur Kenntnis, daß das Kind tot ist und machst entsprechend weiter. Sauberer ist wohl ersteres. In C gibt es außerdem noch die Funktionen wait() und waitpid() um das etwas gepflegter auch mit mehreren Kindern abzuwickeln, vielleicht gibt's die auch in Perl.
Geguckt habe ich bisher in der perldoc unter perlipc und perlfork, große Teile des Scriptes sind den Beispielen dort entnommen.
Das Perl Cookbook kennst Du?
my ($pid,$line); my ($kid,$parent);
Ganz schön viele globale Variablen. Das würde mich gerade bei einem solchen Problem nervös machen. Thorsten -- The true danger is when liberty is nibbled away for expedients. - Edmund Burke
Hi Ratti, Am 26.12.2003 14:04 schrieb Joerg Rossdeutscher:
Ich bastele wieder an meiner Fontsammlung rum, und wie gehabt gibt es das Problem, dass ein beschädigter Font mein Perlscript per Segfault crashen kann. Ich möchte aber das Script weiterlaufen lassen.
Ich habe hier den Tip bekommen, daß das Abfangen von Segfault-Signalen unsauber wäre, da der Prozess sich in einem mehr oder weniger undefinierten Zustand befände. Besser wäre es, einen separaten Prozess zu nutzen, und den wenn der wegbricht, ihn in Frieden sterben zu lassen und einen neuen Prozess zu starten. Joo... klingt gut. Krieg ich aber nicht hin.
http://www.linux-magazin.de/Artikel/ausgabe/2001/08/Perl/perl.html Ist wohl etwas mehr als das was Du brauchst. -Joerg
Am Mo, den 29.12.2003 schrieb jz um 13:54:
http://www.linux-magazin.de/Artikel/ausgabe/2001/08/Perl/perl.html
Ist wohl etwas mehr als das was Du brauchst.
Ui. Ganz viel Bahnhof. Da werde ich mich mal durcharbeiten. Danke! Gruß, Ratti -- -o) fontlinge | Font management for Linux | Schriftenverwaltung in Linux /\\ http://freshmeat.net/projects/fontlinge/ _\_V http://www.gesindel.de https://sourceforge.net/projects/fontlinge/
participants (9)
-
Andre Heine
-
Bernhard Walle
-
Christian Boltz
-
Ferdinand Ihringer
-
Gerald Goebel
-
Jan.Trippler@t-online.de
-
Joerg Rossdeutscher
-
jz
-
Thorsten Haude