[Vienna-pm] symlink: Ungültiger Dateidescriptor

Peter J. Holzer hjp-vienna-pm-list at hjp.at
Sat Jun 21 02:49:17 PDT 2008


On 2008-06-19 19:27:52 +0200, Calli wrote:
> Am Sonntag, 15. Juni 2008 schrieb Peter J. Holzer:
> > On 2008-06-14 23:15:13 +0200, Calli wrote:
> > > Am Samstag, 14. Juni 2008 schrieb Peter J. Holzer:
> > > > On 2008-06-14 10:07:11 +0200, Calli wrote:
> > > > > Am Samstag, 14. Juni 2008 schrieb Lars Dɪᴇᴄᴋᴏᴡ 迪拉斯:
> > > > > > Wie soll man sich ein
> > > > > > klares Bild über das Problem verschaffen?
> > > > >
> > > > > Das ist der etwas geänderte Funktionsaufruf (ich hatte
> > > > > Funktionen):
> > > > >
> > > > >   $tstSL='/ir/gend/wo/tst'; # das dir gibt's und ist 'ganz
> > > > > offen' (777) # ändere Pfad für $_[1] nicht Namen, für mit/ohne
> > > > > Pfad foreach my $oF ( liesFiles('ir/gend/wo/files') ) {
> > > > >    # für Files mit und ohne Pfad
> > > > >     symlink($oF,$tstSL.(($oF =~ /.+\/(.+)/ ) ?  "/$1" :
> > > > > "/$_[1]") ); next if ( $? || $! =~ /exist/ ); # kein Fehler,
> > > > > wenn File exists.
> > > >
> > > > [...]
> > > >
> > > > > > Was mich stutzig macht: "Ungültiger Dateideskriptor" ==
> > > > > > EBADF, aber das ist in man 2 symlink gar nicht aufgeführt.
> > > > > > Überprüfst du Rückgabewerte auf die korrekte Art?
> > > > >
> > > > > Siehe oben mit $? und $!
> > > >
> > > > perldoc perlvar:
> > > >
> > > >        $?      The status returned by the last pipe close,
> > > > backtick ("``") command, successful call to wait() or waitpid(),
> > > > or from the system() operator.
> > > >
> > > >
> > > > perldoc -f symlink:
> > > >
> > > >        symlink OLDFILE,NEWFILE
> > > >                Creates a new filename symbolically linked to the
> > > > old filename. Returns 1 for success, 0 otherwise.
> > >
> > > und ??
> > > das (inkl man symlink) hab ich ja alles auch aufgerufen und 'fühle
> > > mich' ratlos zurückgelassen:
> >
> > Ich hatte gehofft, Du würdest den Fehler sehen, wenn man Dir die zwei
> > relevanten Sätze aus der Doku auf dem Silbertablett präsentiert. Aber
> > offenbar kannst Du diese beiden Sätze nicht mit Deinem Code in
> >
> > Zusammenhang bringen. Also Schritt für Schritt:
> > > > >     symlink($oF,$tstSL.(($oF =~ /.+\/(.+)/ ) ?  "/$1" :
> > > > > "/$_[1]")
> >
> > 1) Wie stellst Du fest, ob symlink funktioniert hat? Gar nicht, denn
> > in
> >
> >    der Doku steht:
> > > > Returns 1 for success, 0 otherwise.
> >
> > Aber den Returnwert von symlink ignorierst Du. Richtig müsste das
> > ungefähr so lauten:
> >
> >     unless (symlink($oF,$tstSL.(($oF =~ /.+\/(.+)/ ) ?  "/$1" :
> > "/$_[1]"))) { # Fehlerbehandlung
> >     }
> ahh, ok! Ich kam vom einen system('..') aufruf,

system() ist das schwarze Schaf unter den Perl-Funktionen. Bei fast
allen heißt ein wahrer Return-Wert, dass es funktioniert hat, bei system
heißt ein wahrer Return-Wert, dass es nicht funktioniert hat. Das ist
zwar verständlich, aber trotzdem inkonsistent. Aber ich finde es
interessant, dass Du ausgerechnet aus der Ausnahme auf die Allgemeinheit
schließt.

> die doku von symlink ist sehr sparsam,

Da spürt man deutlich die Unix-Herkunft von perl. Perl-Funktionen, die
ein direktes Abbild von Unix Systemcalls oder Libraryfunktionen sind,
sind recht spärlich dokumentiert, weil die Dokumentation ja schon beim
System dabei ist (man 2 symlink in dem Fall). Außerdem sind diese
Funktionen u.U. systemabhängig, so dass man sowieso die lokale Manpage
lesen sollte.

> nicht auszuschließen, dass symlink intern ähnlich einem System-Aufruf
> (system('symlink', ..) realisiert ist,

Unter Unix ist das auszuschließen. Symlink ist ein Systemcall. Auf
anderen Systemen funktioniert die Funktion wahrscheinlich gar nicht.

> ausserdem hab ich mir eine Art Fehlerschrotschuß 
> gemacht:
> print "...  ?:$?; !:$!; err:".($? & 127),"<\n";

Und damit alles getroffen, nur nicht das, was Du wolltest. Das
Scharfschützengewehr wäre der Schrotflinte vorzuziehen gewesen.
Du hast es in Deinem Waffenschrank, Du musst es nur benützen:

> > > > Returns 1 for success, 0 otherwise.

Warum weigerst Du Dich so beharrlich, die dokumentierte Methode zu
verwenden und versteifst Dich darauf Methoden zu verwenden, die
dokumentierterweise nicht funktionieren können?

> > > da wird ein Fehler gefunden, den 'gibt's-nicht'.
> >
> > Sowas ist immer ein guter Hinweis darauf, dass mit der Logik der
> > Fehlerbehandlung was nicht stimmt.
> Ähm, wirklich?

Ja. Wenn ein "unmögliches" Ergebnis herauskommt, ist das meiner
Erfahrung nach ein sehr guter Indikator dafür, dass man was falsch
gemacht hat. Ich habe zwar schon im Lauf der Jahrzehnte den einen oder
anderen Bug in Libraries oder Doku gefunden, aber viel häufiger habe
ich Bugs in meinem eigenen Code gefunden.

> Tatsächlich scheint symlink sehr wohl $! zu setzen 

Ja, aber *dann, wenn ein Fehler aufgetreten ist*. 

Also:

    if (symlink($x, $y)) {
	# alles ok. $! enthält irgendeinen Wert, wahrscheinlich den, den
	# es schon vor dem Aufruf von symlink gehabt hat, aber darauf
	# sollte man sich nicht verlassen.
    } else {
	# Es ist ein Fehler aufgetreten. $! enthält die Fehlerursache.
    }

Alle Unix-Systemcalls und viele C-Funktionen verhalten sich so. errno
(das C-Äquivalent von $!) wird gesetzt, wenn ein Fehler aufgetreten ist.

Üblicherweise ist das in "man 2 intro" beschrieben (als Man-Pages noch
Teil von gedruckten Büchern waren, war "intro" jeweils der Anfang jedes
Kapitels - diejenigen von uns, die alt genug sind, noch gedruckte
Manuals zu kennen, haben also den unfairen Vorteil, von der Existenz
dieser Seite zu wissen).

In der Perl-Doku ist das in perldoc perlvar, Abschnitt über "$!"
beschrieben:

|              in other words, if a system or library call fails,
|              it sets this variable.  This means that the value of $! is
|              meaningful only immediately after a failure:
|
|                  if (open(FH, $filename)) {
|                      # Here $! is meaningless.
|                      ...
|                  } else {
|                      # ONLY here is $! meaningful.
|                      ...
|                      # Already here $! might be meaningless.
|                  }
|                  # Since here we might have either success or failure,
|                  # here $! is meaningless.
|
|              In the above meaningless stands for anything: zero, non-zero,
|              "undef".  A successful system or library call does not set the
|              variable to zero.


> (obwohl nix zu stehen scheint, weder bei Perl noch in man).

man 2 symlink (auf Debian Linux):

| RETURN VALUE
|        On  success,  zero is returned.  On error, -1 is returned, and errno is
|        set appropriately.
| 
| ERRORS
[Liste von errno-Werten]

Steht IMHO ziemlich eindeutig da.


> Da wären wir wieder bei meiner Frage, denn symlink setzt $! auf (sowas
> wie) "File existiert", wenn da schon ein Symlink ist. Also hat es
> vorher $! gesetzt auf "Ungültiger Dateideskriptor" 

Nein, das ist ein Fehlschluss. *Irgendwas* hat $! auf "Ungültiger
Dateideskriptor". Wie kommst Du auf die Idee, dass das symlink gewesen sein
soll?

	hp

-- 
   _  | Peter J. Holzer    | Openmoko has already embedded
|_|_) | Sysadmin WSR       | voting system.
| |   | hjp at hjp.at         | Named "If you want it -- write it"
__/   | http://www.hjp.at/ |  -- Ilja O. on community at lists.openmoko.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mail.pm.org/pipermail/vienna-pm/attachments/20080621/b2ab7a6d/attachment.bin 


More information about the Vienna-pm mailing list