frage zu pipe(2)
-
Das sollte da nicht hängen.
man 7 pipe schrieb:
If all file descriptors referring to the read end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be generated for the calling process. If the calling process is ignoring this signal, then write(2) fails with the error EPIPE.
write liefert einen ssize_t zurück, also ein size_t mit Vorzeichen. Wenn der Wert negativ ist (sprich -1), trat ein Fehler auf. Hier sollte dann in errno der Wert EPIPE stehen.
-
Oh. Wichtig ist natürlich, dass du das SIGPIPE Signal auch ignorierst, sonst terminiert der Vater bei dem write, wenn das Leseende geschlossen wird.
#define _POSIX_C_SOURCE 200809L #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <signal.h> #include <unistd.h> int main(void) { sigset_t mask; sigemptyset(&mask); struct sigaction sa = { .sa_handler = SIG_IGN, .sa_mask = mask, .sa_flags = SA_RESTART, }; if (sigaction(SIGPIPE, &sa, 0) == -1) { perror("sigaction"); return EXIT_FAILURE; } int p[2] = {-1, -1}; if (pipe(p) == -1) { perror("pipe"); return EXIT_FAILURE; } pid_t const pid = fork(); if (pid == -1) { perror("fork"); return EXIT_FAILURE; } else if (pid) // Parent { int const tx = p[1]; close(p[0]); // Close read end. while (1) { char const buf[] = "Hello child!"; ssize_t const ret = write(tx, buf, sizeof buf); if (ret == -1) { if (errno == EPIPE) { puts("Child exited."); return EXIT_SUCCESS; } perror("write"); return EXIT_FAILURE; } } } else // Child { int const rx = p[0]; close(p[1]); // Close write end. // Do something … char buf[512] = {0}; ssize_t const ret = read(rx, buf, sizeof buf - 1); if (ret == -1) { perror("read"); return EXIT_FAILURE; } printf("Child read: %s\n", buf); sleep(1); return EXIT_SUCCESS; // Child exits. } return EXIT_SUCCESS; }
-
ich werte den Rückgabewert von write() ja aus. doch obwohl der Sohn Prozess
geschossen ist, bekomme ich keine "-1" von write() im Vater Prozess. Stattdessen
bekomme ich gar nichts mehr. Er bleibt bei write() einfach hängen und tut nichts ./*! * @fn int pipe_read(*char data_in, size_t n_bytes) * @brief sendet daten an die pipe * * @author JJ * @date 9.02.2017 * * @param[out] data_in daten die gesendet wurden sollen * @param[in] n_bytes Anzahl der zu empfangennen Bytes * @return 0: Success * -1: Error * */ int pipe_write(void* data_out, size_t n_bytes) { ssize_t retval=0; retval = write(pipefd.send,data_out,n_bytes); if(retval != (ssize_t)n_bytes) { printf("TIDASERVER: %s -> pipe_write error %d, %s\n",__FUNCTION__, errno, strerror(errno)); return -1; } printf("%d %d \n",n_bytes,retval); return 0; }
-
Client ist verbunden
ps PID TTY TIME CMD 1012 ttymxc0 00:00:00 sh 1070 ttymxc0 00:00:00 tidaserver_jj 1071 ttymxc0 00:00:01 tidaserver_jj 1072 ttymxc0 00:00:00 tidaserver_jj 1073 ttymxc0 00:00:00 ps
Client schlisst die Verbindung
ps PID TTY TIME CMD 1012 ttymxc0 00:00:00 sh 1055 ttymxc0 00:00:00 tidaserver_jj 1056 ? 00:00:00 tidaserver_jj <defunct> 1058 ttymxc0 00:00:00 ps
die ausgabe:
483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 483840 TIDASERVER: tcp_write -> Client socket write error 0, Success TIDASERVER: process2 -> ende Sohn process weil tcp get nicht TIDASERVER: pipe_close -> close Pipe TIDASERVER: tcp_close_client_socket -> close Client Socket TIDASERVER: tcp_close_server_socket -> close Server Socket
danach kommt nichts mehr.
-
Sorry schwer von begriff!
sigset_t mask; sigemptyset(&mask); struct sigaction sa = { .sa_handler = SIG_IGN, .sa_mask = mask, .sa_flags = SA_RESTART, }; if (sigaction(SIGPIPE, &sa, 0) == -1) { perror("sigaction"); return EXIT_FAILURE; }
da ist der Punkt gewesen.
-
Joachim Jähn schrieb:
Sorry schwer von begriff!
sigset_t mask; sigemptyset(&mask); struct sigaction sa = { .sa_handler = SIG_IGN, .sa_mask = mask, .sa_flags = SA_RESTART, }; if (sigaction(SIGPIPE, &sa, 0) == -1) { perror("sigaction"); return EXIT_FAILURE; }
Wo war denn da das Problem genau?
da ist der Punkt gewesen.
-
da war kein Problem. das habe ich nicht gemacht. deswegen wurde der Vater Prozess terminiert. ich habe diesen Codeblock in meine pipe_init() übernommen. das hat geholfen. sihe Biolunar's beispiel.
-
das ganze läuft schon fast richtig. aber
jetzt erkennt der Vater das der Sohn nicht mehr da ist und schließt alle Verbindungen und fürt ein exit(EXIT_SUCCESS); aus
trotzdem liefert mir
ps 1159 ? 00:00:00 tidaserver_jj <defunct>
while(!waitpid(pid, 0,WNOHANG)) //mainloop solange Shon Process noch aktive { switch(cam_read_frame()) { case 0: printf("nF "); break; case -1: // fehler read Freame. was tun? default: for(size_t i=0; i < cam_read_buffer_size/sizeof(uint16_t); i++) { cam_read_buffer[i]=cam_read_buffer[i] >> 6; } pipe_write(cam_read_buffer,cam_read_buffer_size); } } printf("TIDASERVER: %s -> ende Vater Prozess weil Shon Prozess beendet\n",__FUNCTION__); pipe_close(); tcp_close_client_socket(); tcp_close_server_socket(); exit(EXIT_SUCCESS); }
-
Ok das Problem ist was anderes. hängt mit fork() zusammen.
Der main Server Starte via fork() Prozess1 und Prozess1() startet via fork() Prozess2().
Wenn Prozess2() beendet wird fragt Prozess1() den Status Prozess2 ab und beendet sich selbst. weil der main Server den Status des von Prozess1 nie ab fragt, bleibt ein Zombi von Prozess1 zurück.
Dem main Server interessiere es nicht ob Prozess1 noch da ist oder nicht.
Wie wird man in diesen Fall die Zomis wieder los? ( außer mit ner Shotgan )
-
Für jedes fork() brauchst du ein wait oder waitpid im Elternprozess um Zombies zu entfernen. Du kannst z.B. auf das SIGCHLD Signal im Elternprozess warten und im Signalhandler dann wait aufrufen.