Schrift
Wiki:Tipp zum Debugging: use Data::Dumper; local $Data::Dumper::Useqq = 1; print Dumper \@var;
[thread]8539[/thread]

eval stoppen

Leser: 1


<< |< 1 2 >| >> 17 Einträge, 2 Seiten
Gast Gast
 2006-11-29 17:33
#72069 #72069
Hallo!

Ich habe eine Perl/Tk Anwendung, die auch einen Texteditor enthällt, welcher Perl Skripte verwltet.
Die Perl Skripte sollen ausgeführt werden können, aber Ihre Ausführung muss auch gestoppt werden können.

Im Moment führe ich die Programme mit eval aus.
Aber ich weiß nicht wie ich es schaffe die Ausführung anzuhalten.

Ich habe schon das Forum und Google durchsucht, aber finde einfach nichts was mir da weiterhilft.
Dazu habe ich mir auch mal threads angesehen, allerdings hat vollgendes Beispiel auch nicht das gewünschte Erbegnis erzielt:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/perl
use strict;
use warnings 'all';
use Tk;
use threads;

my $thr = threads->new(sub { (print("An!\n"), sleep 1) while 1 });
my $mw  = tkinit;

$mw->Button(-text => "Start", -command => sub { threads->yield; $thr->join })->pack;
$mw->Button(-text => "Stop!", -command => sub { $thr->detach })->pack;

MainLoop;


Als ich das ausprobiert habe ist mir nur aufgefallen, dass join() wohl den thread nicht startet, sondern ihm die volle "Aufmerksamkeit" gibt. Und, dass detach() den thread nicht beendet, sondern in quasi löscht.

Warscheinlich kann man mein Problem mit threads lösen, nur ich weiß eben nicht wie, vielleicht kann man aber auch eval stoppen und ich habe noch nicht herausgefunden wie das funktioniert.

Ich freue mich über alle Arten von Anregungen.

- Perl Anfänger -
sid burn
 2006-11-29 18:37
#72070 #72070
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Als ich das ausprobiert habe ist mir nur aufgefallen, dass join() wohl den thread nicht startet, sondern ihm die volle "Aufmerksamkeit" gibt. Und, dass detach() den thread nicht beendet, sondern in quasi löscht

join() ist dafür da um den Rückgabewert eines Threads auszulesen. Wenn der Thread noch nicht beendet wurde, bockiert join solange bis ein Rückgabewert vorhanden ist.

Mit detach() sagst du das der Rückgabewert letztendlich Verworfen werden soll wenn der Thread fertig ist. Daher du sparst dir das Manuelle aufrufen von join(). Kannst dann aber auch nicht mehr den Rückgabewert auslesen.

Der Thread selber läuft schon nachdem du "threads->new()" aufgerufen hast.


Ansonsten fällt mir zur Zeit nur eine Möglichkeit mit SIGALRM ein um einen Codeabschnitt nach einer bestimmten Zeit abbrechen zu lassen.

Das Codeschnipel hier unten gibt einen 5 Sekunden Zeit für eine Eingabe und bricht nach der Zeit ab.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl
use warnings;
use strict;

alarm(5);
eval {
$SIG{ALRM} = sub { die "timeout" };
print "Name eingeben: ";
my $input = <STDIN>;
alarm(0);
};
alarm(0);
die "Die Zeit ist abgelaufen...\n" if $@ =~ m/timeout/;
die "Error: $@\n" if $@;


Das ganze kannst du sicherlich auch mit fork() koppeln. Wie gut das alles mit threads funktioniert weiß ich nicht.

Und wie gut das ganze auch noch innerhlab einer GUI läuft kann ich noch weniger sagen.\n\n

<!--EDIT|sid burn|1164819151-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
PerlProfi
 2006-11-29 21:46
#72071 #72071
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Lieder muss das ganze auch auf Windows laufen ;)
Und es soll ja nicht nach einer bestimmten Zeit stoppen, sondern bei einem bestimmten Ereignis.

Es wäre natürlicher das Beste, wenn ich das Perl Skript Schritt für Schritt durchlaufen könnte, dann könnte ich jederzeit stoppen, und auch noch anzeigen an welcher Position man sich gerade befindet.
Ich habe auch schon danach gesucht, aber bis jetzt noch nichts gefunden.
Gibt es vielleicht schon ein Modul das genau das macht ?

Oder kann man doch irgendwie eval stoppen lassen?

- Perl Anfänger -
sid burn
 2006-11-29 21:59
#72072 #72072
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Und es soll ja nicht nach einer bestimmten Zeit stoppen, sondern bei einem bestimmten Ereignis.

Ich weiß nicht wie dein Ereignis ausschaut, aber du kommst aus einem eval() ganz normal mit die() heraus.

Dies setz auch gleichzeitig die Variable $@ und diese Variable kannst du danach auch überprüfen, und dann feststellen welches Ereignis eingetroffen ist.

Quote
ieder muss das ganze auch auf Windows laufen
Die obere Methode sollte mit einer ActiveState Version 5.8 oder so Funktionieren. Ansonsten wurde fork() auf Windows Portiert.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
PerlProfi
 2006-11-29 22:13
#72073 #72073
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
[quote=sid burn,29.11.2006, 20:59]Ich weiß nicht wie dein Ereignis ausschaut, aber du kommst aus einem eval() ganz normal mit die() heraus.[/quote]
Ein Ereignis wäre zum Beispiel, dass der Benutzer in meiner Applikation auf einen Button drückt.

Ich weiß schon, dass ich mit die() aus eval() herauskomme, aber mit eval() führe ich ja nur den Code aus der in meinem Textfeld steht.
Und falls dieser Code eine Entlosschleife enthällt, begibt sich mein Programm leider auch in eine Endlosschleife, dass ist das Problem, andere Fehler fange ich mit eval{} ab und gebe sie aus, nachdem das Skript abgelaufen ist.

Hier mein Konstrukt:
Code: (dl )
1
2
3
4
5
6
7
8
eval
{
# hier kann es jetzt hängen bleiben:
eval("Inhalt vom Textfeld");

# Fehlermeldungen ausgeben
errorMsg($@) if $@;
}


[quote=sid burn,29.11.2006, 20:59]Die obere Methode sollte mit einer ActiveState Version 5.8 oder so Funktionieren. Ansonsten wurde fork() auf Windows Portiert.[/quote]
Ja fork() funktioniert, aber das Signal ALRM kennt Windows leider nicht.\n\n

<!--EDIT|PerlProfi|1164831259-->
renee
 2006-11-29 22:54
#72074 #72074
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Doch, bei Perl 5.8 sollte SIG{ALRM} funktionieren...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
sid burn
 2006-11-30 10:54
#72075 #72075
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Ich habe nochmals mit fork() herumgespielt, und folgendes lief auch unter Windows mit ActivePerl

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
use strict;
use warnings;

sub child {
$SIG{TERM} = sub { exit 0 };
for ( 1 .. 10 ) {
print "Child: $_\n";
sleep 1;
}
exit 0;
}

die "Cannot fork: $!\n"
unless defined( my $pid = fork );

$pid || child;

for ( 1 .. 10 ) {
print "Parent: $_\n";
kill 15 => $pid if $_ == 5;
sleep 1;
}


Ich weiß allerdings nicht wieviele Probleme es unter Windows noch zusätzlich bereiten kann. in "perldoc perlfork" steht das es Memory Leaks verursachen kann!?\n\n

<!--EDIT|sid burn|1164876975-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
PerlProfi
 2006-11-30 15:07
#72076 #72076
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Ich benutze fork() nicht so häufig, und auch die Signale nicht, aber ich habe dein erstes Beispiel bei mir getestet(Windows XP, ActivePerl 5.8.8) und es hat nicht nach 5 sek beendet.

Dein zweites Beispiel mit fork() funktioniert, allerdings weiß ich nicht wie mir das helfen soll eval zu stoppen sobald ein entsprechendes Ereignis auftritt?

Danke trotzdem für deine Bemühungen, ich such dann nochmal alles durch, warscheinlich sehe ich mir mal den Code dr Open Perl IDE an, dort kann man ja auch Schritt für Schritt durch den Code gehen, genau das was ich brauche.

MfG PerlProfi\n\n

<!--EDIT|PerlProfi|1164892172-->
sid burn
 2006-11-30 15:42
#72077 #72077
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Quote
Dein zweites Beispiel mit fork() funktioniert, allerdings weiß ich nicht wie mir das helfen soll eval zu stoppen sobald ein entsprechendes Ereignis auftritt?

Du forkst, und läst deinen Code im Child Prozess mit eval laufen.
Deine GUI wird dann im Parent Prozess weiter laufen, und wenn du das Event bekommst von ein Button der gedrückt wurde, kannst du ja ein kill signal vom Parent zu den entsprechenden Child Prozess senden. Somit wird dan dein eval code unterbrochen.

Problematisch ist halt nur das Windows eigentlich kein fork kann, eigentlich ist es auch kein parent und kein child Prozess. Und alles wird über Threads gelöst. Kann also nicht sagen welche Probleme ggf. noch durch solch eine Lösung entstehen könnten.\n\n

<!--EDIT|sid burn|1164894247-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
PerlProfi
 2006-11-30 15:53
#72078 #72078
User since
2006-11-29
340 Artikel
BenutzerIn
[default_avatar]
Sehr vielen Dank!!!
Ich werde das gleich mal einbauen.

Das war dann das letzte was noch gefehlt hat in der Applikation.
Schade das ich nicht Schritt für Schritt durch den Code gehe, aber wenn das so funktioniert bin ich schon sehr zufrieden.

MfG PerlProfi
<< |< 1 2 >| >> 17 Einträge, 2 Seiten



View all threads created 2006-11-29 17:33.