Wie finde ich den richtigen File anhand von Filedescriptor heraus?

13/11/2007 - 15:14 von Michel Strähl | Report spam
Hallo

ich schlage mich mit einem (für mich) etwas vetrackten Problem herum:
In einer Applikation (in C geschrieben) soll ein Report geschrieben
werden. Die Daten werden per pipe übertragen.
Anhand von truss -f kann ich feststellen, dass einige Files mittels
Filedescriptoren (FD) geöffnet und wieder geschlossen werden und mit
der gleichen FD-Nummer (z.B. 3) wird ein anderer File geöffnet und
wieder geschlossen, etc.
In diesen Fàllen kann ich (meine ich zumindestens) erkennen, um
welchen File es sich handelt:
open("/var/ld/ld.config", O_RDONLY) = 3
...
close(3)
...
open("/tools/oracle/product/10.1/lib32/libclntsh.so.10.1", O_RDONLY) 3
...
close(3)
Gehe davon aus, dass das FD 3 ist.

Làuft die Applikation mit eingeschaltetem Trace ("selber" geschriebene
Funktion resp übernommen), dann làuft die Applikation problemlos. Ist
Trace ausgeschaltet, dann bleibt die Applikation hàngen. Das Ein- und
Ausschalten erfolgt über ein env-Variable (setenv TRACE_LEVEL 0 resp
1)

Ich habe auch herausfinden können, wo der Absturz geschieht. Es
geschieht in dem Moment, in dem auf eine pipe geschrieben werden soll,
die den FD 19 hat. Mit eingeschaltetem Trace hat die gleiche pipe den
FD 21, dann geht es.
Ich habe beide truss-Ausgaben verglichen und neben den
unterschiedlichen FD-Nummern (und natürlich den pids) ist eigentlich
alles (fast) gleich. Ich also "optisch" keinen Unterschied
feststellen, trotzdem muss einer da sein, ansonsten würde nicht einmal
FD 19 verwendet und beim anderen Mal FD 21.

Leider habe ich nicht heraus finden können, was hinter FD 19 resp 21
steckt. Einziger Anhaltspunkt:
(im Fehlerfall)
lwp_create(0xFC80F9A0, LWP_DETACHED|LWP_SUSPENDED, 0xFC70DDE4) = 19
lwp_create() (returning as new lwp ...) = 0
lwp_continue(19) = 0
lwp_schedctl(SC_STATE|SC_BLOCK, -1, 0xFC70DCD4) = 0
lwp_schedctl(SC_DOOR, 0, 0x00000000) = 3

(im Okay-Fall)
lwp_create(0xFBC0F9A0, LWP_DETACHED|LWP_SUSPENDED, 0xFBB0DDE4) = 19
lwp_create() (returning as new lwp ...) = 0
lwp_continue(19) = 0
lwp_schedctl(SC_STATE|SC_BLOCK, -1, 0xFBB0DCD4) = 0
lwp_schedctl(SC_DOOR, 0, 0x00000000) = 3
resp
lwp_create(0xFC60B9A0, LWP_DETACHED|LWP_SUSPENDED, 0xFC509DE4) = 21
lwp_create() (returning as new lwp ...) = 0
lwp_continue(21) = 0
lwp_schedctl(SC_STATE|SC_BLOCK, -1, 0xFC509CD4) = 0
lwp_schedctl(SC_DOOR, 0, 0x00000000) = 3

(Nehme mal an, dass das die FDs sind)

Ich habe schon versucht, anstatt via der erwàhnten Trace-Funktion
direkt in ein File zu schreiben. Funktioniert einwandfrei,
Fehlverhalten bleibt sich aber in beiden Fàllen gleich (mit Trace
okay, ohne Trace Hànger). Sehe auch den FD zu diesem zusàtzlichen File
im truss.

Wie finde ich also heraus, was genau FD 19 zugeordnet ist? Warum kann
ich mal in diese pipe (wenn FD 21) schreiben und warum mal nicht (wenn
FD 19)?

Hier ist wohl die entsprechende Stelle im truss:
write(19, " D", 1) Err#9 EBADF

wàhrend im Okay-Fall
write(21, " D", 1) = 1

Ja, FD 19 wird mal geschlossen ;-) Aber warum? Wann? Welche Funktion?
Aber kurz danach, kommt folgende truss-Angabe:

close(19) Err#9 EBADF
fcntl(3, F_DUPFD, 0x00000013) = 19
close(3) = 0
fcntl(19, F_SETFD, 0x00000001) = 0
ioctl(2, TCGETA, 0xFFBED14C) Err#25 ENOTTY
read(19, " # ! / b i n / s h #".., 128) = 128
read(19, " e / p r o d u c t / d e".., 128) = 128
brk(0x0003D4A0) = 0
read(19, " e x p o r t F O R M".., 128) = 128

Das close(19) antwortet mit EBADF, aber 2 Zeilen spàter wird es meiner
Meinung nach mit fcntl wieder geöffnet und ausgelesen?!?
Dieser Teil ist ebenfalls bei beiden Fàllen gleich.

Leider habe ich auf diesem Gebiet selber zu wenig Erfahrung, um heraus
zufinden, was da genau schief làuft. Daher weiss ich auch nicht genau,
was für Angaben ihr noch braucht (und wie ich die ggf herausfinden
kann), um mir ggf helfen zu können.

Machine hardware: sun4u
OS version: 5.8
Processor type: sparc
Hardware: SUNW,Sun-Fire-V240

Hier der Code, an dem der Fehler auftritt:

Write_Fmt_Rpt_To_Pipe(writepipe, formatted_report)
INT writepipe;
TEXT_LINES **formatted_report;
{
TEXT_LINES *text_lines_ptr;
TEXT_LINES text_lines_struct;
INT text_lines_size;
static CHAR function_name[] = "Write_Fmt_Rpt_To_Pipe";

text_lines_size = sizeof(TEXT_LINES);

for (text_lines_ptr = *formatted_report; text_lines_ptr != NULL;
text_lines_ptr = text_lines_ptr->next)
{
/* Free side list, not used across pipe */
if (text_lines_ptr->report_data.element_type == ET_UNIVERSAL)
{
Link_List_Free(&(text_lines_ptr->report_data.unit_key_list),
NULL);
}
if (write(writepipe, text_lines_ptr, text_lines_size) ! text_lines_size)
{
return(FAILURE);
}
}
...
}

Übergebene Parameter:
writepipe: 21 (resp 19 im Fehlerfall)
text_lines_size: 1196 (in beiden Fàllen)
text_lines_ptr->report_data.element_type: 0 (in beiden Fàllen)

Die aufgeführte Konstante ET_UNIVERSAL hat folgende Definition:
#define ET_UNIVERSAL 27
Der Element-Type in diesem Fall ist 0, also wird die Funktion
Link_List_Free nicht aufgerufen.

Vielen Dank
Michel

P.S:
wie könnte ich zu Testzwecken im Fall ohne Trace-Funktion einen
weiteren FD generieren, damit ich testen kann, ob dann ebenfalls FD 21
verwendet wird?
 

Lesen sie die antworten

#1 Markus Raab
13/11/2007 - 16:17 | Warnen spam
Michel Stràhl wrote:

Wie finde ich also heraus, was genau FD 19 zugeordnet ist? Warum kann
ich mal in diese pipe (wenn FD 21) schreiben und warum mal nicht (wenn
FD 19)?



ls -l /proc/<pid>/fd

Sagt dir welcher fd was gerade geöffnet hat.

mfg Markus

Ähnliche fragen