Toon posts:

[C] pipe() blijft hangen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben een kleine shell aan het schrijven die commando's met een pipe '|' moet kunnen uitvoeren, maar nu heb ik het probleem dat mijn shell blijft hangen als ik bijvoorbeeld het commando "ls | wc" intik. Ik denk dat dit komt omdat het process dat het commando "wc" uitvoert maar blijft wachten op input (de output van process dat "ls" uitvoert). Hoe kan ik dit oplossen?
Code ziet er alsvolgt uit:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 pid1 = fork();
      if (pid1 == -1) {
    return -1;
      }         
      if (pid1 == 0) { // CHILD
    pid2 = fork();
    if (pid2 == -1) {
      return -1;
    }           
    if (pid2 == 0) {   // CHILD
      if ((close(1)) < 0) {      
        return -1;
      }
      if ((dup(fd[1])) < 0) {  
        return -1;
      }
      if ((close(fd[0])) < 0) { 
        return -1;
      }
      if((execvp(params1[0], params1)) == -1) {  
        fprintf(stdout,"%s: Unknown command\n", params1[0]);
        break;
      }
           exit(0);
    }
    else {   // PARENT
      if ((close(0)) < 0) {     
        return -1;
      }
      if ((dup(fd[0])) < 0) {  
        return -1;
      }
      if ((close(fd[1])) < 0) { 
        return -1;
      }
      if((execvp(params2[0], params2)) == -1) {  
        fprintf(stdout,"%s: Unknown command\n", params1[0]);
        break;
      } 
      wait(0); 
    }
    exit(0);
      }         
      else {  // PARENT
    wait(0);  
      }


modbreak: gebruik aub zelf [code=c] tags om je code leesbaar te houden, scheelt mij werk :)

[ Voor 10% gewijzigd door curry684 op 02-03-2004 16:54 ]


Verwijderd

Ik vind je vraag niet echt duidelijk en je source is al helemaal onleesbaar. Gebruik even de [CODE] tag. Dan leest Cristal het nog is :)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Je hebt vanzelfsprekend zelf al gestept door de code en/of middels tactisch geplaatste printf's gecontroleerd op welke statement hij hangt?

Oftewel: heb je al gedebugged of moeten wij dat voor je doen? :)

offtopic:
en ik heb trouwens al een schijthekel aan openingsaccolades achteraan de regel plaatsen, maar als je vervolgens ook nog zo inconsequent als wat bent met je indentering wordt het geheel helemaal onbegrijpelijk :X

[ Voor 35% gewijzigd door curry684 op 02-03-2004 16:56 ]

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
De reindented versie (voor andere mensen die allergisch zijn voor slecht geindenteerde code):
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
pid1 = fork();
if (pid1 == -1) {
    return -1;
}
if (pid1 == 0) { // CHILD
    pid2 = fork();
    if (pid2 == -1) {
        return -1;
    }
    if (pid2 == 0) {   // CHILD
        if ((close(1)) < 0) {
            return -1;
        }
        if ((dup(fd[1])) < 0) {
            return -1;
        }
        if ((close(fd[0])) < 0) {
            return -1;
        }
        if((execvp(params1[0], params1)) == -1) {
            fprintf(stdout,"%s: Unknown command\n", params1[0]);
            break;
        }
        exit(0);
    }
    else {   // PARENT
        if ((close(0)) < 0) {
            return -1;
        }
        if ((dup(fd[0])) < 0) {
            return -1;
        }
        if ((close(fd[1])) < 0) {
            return -1;
        }
        if((execvp(params2[0], params2)) == -1) {
            fprintf(stdout,"%s: Unknown command\n", params1[0]);
            break;
        }
        wait(0);
    }
    exit(0);
}
else {  // PARENT
    wait(0);
}

Verwijderd

Topicstarter
curry684 schreef op 02 maart 2004 @ 16:55:
Je hebt vanzelfsprekend zelf al gestept door de code en/of middels tactisch geplaatste printf's gecontroleerd op welke statement hij hangt?

Oftewel: heb je al gedebugged of moeten wij dat voor je doen? :)
dit wordt uitgevoerd
C:
1
2
3
4
5
if ((execvp(params1[0], params1)) == -1) 
{  
        fprintf(stdout,"%s: Unknown command\n", params1[0]);
        break;
}


maar dit
C:
1
2
3
4
5
if ((execvp(params2[0], params2)) == -1)
 {  
        fprintf(stdout,"%s: Unknown command\n", params1[0]);
        break;
}  

blijft hangen omdat dit child proces (althans dat is wat ik denk) blijft wachten op input, hij heeft de output van "ls" al gelezen, maar kan niet bepalen of er nog meer komt, dus blijft hij wachten, terwijl het andere proces al exit(0) heeft uitgevoerd.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Heb je de documentatie van execvp al wel eens gelezen? :?

Professionele website nodig?


Verwijderd

Topicstarter
curry684 schreef op 02 maart 2004 @ 17:15:[/b]
Heb je de documentatie van execvp al wel eens gelezen? :?
ja

bedoel je dat de exit(0) na de execvp nooit uitgevoerd wordt?
dat maakt toch geen verschil? ofwel?

[ Voor 8% gewijzigd door Verwijderd op 02-03-2004 17:19 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op 02 maart 2004 @ 17:18:
[...]
ja

bedoel je dat de exit(0) na de execvp nooit uitgevoerd wordt?
dat maakt toch geen verschil? ofwel?
Ik vraag me af of je wel het goede programma zit te debuggen :D

Professionele website nodig?


Verwijderd

Topicstarter
curry684 schreef op 02 maart 2004 @ 17:20:
[...]

Ik vraag me af of je wel het goede programma zit te debuggen :D
hoe bedoel je?
ik vat je niet echt....sorry

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Verwijderd schreef op 02 maart 2004 @ 17:24:
[...]
hoe bedoel je?
ik vat je niet echt....sorry
Nevermind ik zat scheef te kijken :X Ik moet me als Windowshippie niet bemoeien met Linux-code :z

Professionele website nodig?


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
Hoe kan een exec call nu blijven hangen? Ofwel hij faalt (en dan krijg je een foutmelding terug) ofwel je huidige proces wordt overschreven en dan krijg je dus geen return value meer terug.

Waar is trouwens die eerste fork voor bedoeld? Want in het parent process doe je niets dan wachten op het child process; het lijkt mij dat je dan net zo goed de hele fork operatie achterwege kan laten.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Soultaker schreef op 02 maart 2004 @ 17:34:
Hoe kan een exec call nu blijven hangen? Ofwel hij faalt (en dan krijg je een foutmelding terug) ofwel je huidige proces wordt overschreven en dan krijg je dus geen return value meer terug.
Dat bedoelde ik ook met 'je zit in het verkeerde proces' maar zag toen pas dat de testcase 2 native Linux-operaties zijn (is wc toch ook?). Ergo de exec zelf kan niet hangen, dus moet het hier ergens in de code zitten... denk ik :P

Professionele website nodig?


Verwijderd

Topicstarter
Soultaker schreef op 02 maart 2004 @ 17:34:
Hoe kan een exec call nu blijven hangen? Ofwel hij faalt (en dan krijg je een foutmelding terug) ofwel je huidige proces wordt overschreven en dan krijg je dus geen return value meer terug.

Waar is trouwens die eerste fork voor bedoeld? Want in het parent process doe je niets dan wachten op het child process; het lijkt mij dat je dan net zo goed de hele fork operatie achterwege kan laten.
Hij blijft denk ik hangen in de zin van dat hij niet weet of hij nog meer input krijgt (output van "ls"), dus blijft hij wachten, hij moet volgens mij iets van EOF lezen ofzo, of de pipe moet geclosed worden. Ik heb al geprobeerd om de pipe te closen, maar ook dat werkt helaas niet.

De parent van de eerste fork() is de shell zelf, die loopt weer terug om het volgende commando te lezen en te executen

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
Ik zal het probleem dan wel weer niet snappen. Dit is trouwens ook het eerste topic met pipe() in de titel waar geen pipe() in voorkomt. 8)7

Ok, het gaat dus om het correct verbinden van streams? Of gaat het erom dat de shell blijft hangen?

Wat was precies de bedoeling met die streams? Wat je nu namelijk doet, is stdout afsluiten, stdin op de file descriptor van stdout zetten, en vervolgens de originele stdin ook sluiten. Je nieuwe proces heeft dan dus een gesloten file descriptor 0 en een open file descriptor 1 waar 'ie z'n invoer uit moet gaan lezen. Die configuratie slaat natuurlijk nergens op; dat kan nooit de bedoeling zijn.

Verder heb je om een stream via een pipe om te leiden natuurlijk wel ergens een pipe call nodig. Ik zie 'm nu niet.

[ Voor 111% gewijzigd door Soultaker op 02-03-2004 17:50 ]


Verwijderd

Topicstarter
Soultaker schreef op 02 maart 2004 @ 17:43:

Ok, het gaat dus om het correct verbinden van streams? Of gaat het erom dat de shell blijft hangen?

Wat was precies de bedoeling met die streams? Wat je nu namelijk doet, is stdout afsluiten, stdin op de file descriptor van stdout zetten, en vervolgens de originele stdin ook sluiten. Je nieuwe proces heeft dan dus een gesloten file descriptor 0 en een open file descriptor 1 waar 'ie z'n invoer uit moet gaan lezen. Die configuratie slaat natuurlijk nergens op; dat kan nooit de bedoeling zijn.

Verder heb je om een stream via een pipe om te leiden natuurlijk wel ergens een pipe call nodig. Ik zie 'm nu niet.
Het gaat erom dat de shell blijft hangen.

close(1) sluit stdout af, met een dup(fd[1]), krijg ik een filedescriptor terug met 1, dus stdout is de pipe geworden en omdat ik niet hoeft te lezen van de pipe sluit ik fd[1] af. En omgekeerd om ervoor te zorgen dat de pipe stdin wordt, dus close(0), dup(fd[0]) en close(fd[0])

pipe staat er inderdaad niet bij, ik heb namelijk niet de gehele code gepost.
Maar dat is OK, de shell kan namelijk m.u.v. een piped commando al het andere werk netjes executen, alleen bij bijv. "ls | wc" blijft ie hangen en gebeurt er niks meer

bedoeling van de streams is dat het eerste child "ls" uitvoert (zie execvp met params1) en de output ervan naar een pipe schrijft (pipe is stdout voor dit proces), waar het tweede child dat "wc" uitvoert (zie execvp met params2) uit leest (pipe is stdin voor dit proces). Eerste process, oftewel de "ls" wordt prima uitgevoerd en output wordt naar pipe geschreven, maar process wat "wc" uitvoert blijft maar wachten, heb ik het idee.

[ Voor 21% gewijzigd door Verwijderd op 02-03-2004 18:08 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:03
Aha ok, ik had te snel gelezen. Ik had die array fd over het hoofd gezien (die wordt ook nergens in je code gedeclareerd of geinitaliseerd misschien mede daardoor). Maar ik begrijp wat je wil doen en op het eerste gezicht lijkt het goed.

Heb je al eens geprobeerd om alleen het eerste commando uit te voeren? (Die is in principe niet afhankelijk van de invoer van een ander programma.) Werkte dat wel? En zo niet: probeer het dan nog eens zonder je file descriptors anders in te stellen (dat maakt voor die test toch niet uit en dan zie je tenminste wat er gebeurt).

Verwijderd

Topicstarter
Soultaker schreef op 02 maart 2004 @ 20:17:

Heb je al eens geprobeerd om alleen het eerste commando uit te voeren? (Die is in principe niet afhankelijk van de invoer van een ander programma.) Werkte dat wel? En zo niet: probeer het dan nog eens zonder je file descriptors anders in te stellen (dat maakt voor die test toch niet uit en dan zie je tenminste wat er gebeurt).
Als ik de beide commando's zonder pipe uitvoer, dan worden ze beiden prima uitgevoerd. Ook heb ik met pipe het commando "ls | more" uitgevoerd, dan wordt de output van ls netjes door more uitgeprint, maar daarna blijft ie weer hangen, hij sluit niet af na het uitprinten van de output van ls. ik kom er maar niet uit 8)7
Pagina: 1