C: fifo lesen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: C: fifo lesen

Beitrag von RobertDebiannutzer » 24.08.2018 20:55:13

Hmmja, aber ich weiß nicht, was ich damit machen soll. Ich habe ja keinen Fehler in dem Sinn.

Das Bizarre ist, dass mittels printf-Debugging klar wird, dass der Inhalt des XPending-Loops nicht ausgeführt wird. Aber wenn ich den Loop auskommentiere, funktioniert das Setzen des Titels des RootWindows nicht mehr...

printf-Debugging:

Code: Alles auswählen

Before XPending.
After XPending.
Before select.
After select.
Before continue.
Before XPending.
After XPending.
Before select.
After select.
Before continue.
Before XPending.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
After XPending.
Before select.
After select.
Before continue.
Before XPending.
After XPending.
Before select.
After select.
Before continue.
Before XPending.
After XPending.
Before select.
After select.
Before error.
select: Interrupted system call
After error.
Before end.
After end.
Erst drei Leerläufe, dann fünf writes hintereinander, dann nichts mehr und dann shutdown.

Der printf-Debugging-Code:

Code: Alles auswählen

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <X11/Xlib.h>

/* BEGIN: user configuration */
static const char program_name[] = "myxd";
/* static const char fifo[] = "/tmp/dwmblocks_fifo_intern"; */
static const char fifo[] = "/home/user/fifo";
/* END: user configuration */

static int finish;

static void
term_hdl (int signum)
{
	/* if we do not use signum, gcc complains */
	if (signum == SIGTERM) {
		finish = 1;
	}
}

int
main(void)
{
	static char *display_name = NULL;
	static char name[BUFSIZ];

	static int fd;
	static int rc;
	static int screen;
	static int state = EXIT_SUCCESS;
	static Window root;

	static Display *dpy;
	static struct sigaction term_act;
	static struct timeval tv;
	static XEvent ev;

	fd_set rfds; /* fixed size buffer */

	memset(&term_act, 0, sizeof(term_act));
	term_act.sa_handler = term_hdl;
	if (sigaction(SIGTERM, &term_act, NULL) < 0) {
		perror("sigaction");
		exit(EXIT_FAILURE);
	}

	dpy = XOpenDisplay(display_name);
	if (dpy == NULL) {
		fprintf(stderr, "%s:  unable to open display '%s'\n",
				program_name, XDisplayName(display_name));
		exit(EXIT_FAILURE);
	}
	root = RootWindow(dpy, screen);

	fd = open(fifo, O_RDWR | O_NONBLOCK);
	if (fd == -1) {
		perror("open");
		XCloseDisplay(dpy);
		exit(EXIT_FAILURE);
	}

	while (finish == 0) {
		printf("Before XPending.\n");
		while (XPending(dpy)) {
			printf("Before XNextEvent.\n");
			XNextEvent(dpy, &ev);
			printf("After XNextEvent.\n");
		}
		printf("After XPending.\n");
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		printf("Before select.\n");
		rc = select(fd + 1, &rfds, NULL, NULL, &tv);
		printf("After select.\n");
		if (rc > 0) { /* success */
			memset(name, 0, sizeof(name));
			printf("Before read.\n");
			ssize_t got = read(fd, name, sizeof(name)-sizeof(char));
			printf("After read.\n");
			if (got < 0) {
				perror("read");
				state = EXIT_FAILURE;
				break;
			} else if (got == 0) {
				printf("EOF\\n");
				break;
			} else {
				/* remove trailing newline */
				if ((*name) && (name[strlen(name)-1] == '\n')) {
					name[strlen(name)-1] = '\0';
				}
				printf("Before XStoreName.\n");
				XStoreName(dpy, root, name);
				printf("After XStoreName.\n");
			}
		} else if (rc == 0) { /* timeout expired */
			printf("Before continue.\n");
			continue;
			printf("After continue.\n");
		} else { /* error */
			printf("Before error.\n");
			perror("select");
			state = EXIT_FAILURE;
			printf("After error.\n");
			break;
		}
	}
	printf("Before end.\n");
	close(fd);
	XCloseDisplay(dpy);
	printf("After end.\n");
	exit(state);
}

Benutzeravatar
bluestar
Beiträge: 2334
Registriert: 26.10.2004 11:16:34
Wohnort: Rhein-Main-Gebiet

Re: C: fifo lesen

Beitrag von bluestar » 25.08.2018 02:51:54

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
24.08.2018 20:55:13
Das Bizarre ist, dass mittels printf-Debugging klar wird, dass der Inhalt des XPending-Loops nicht ausgeführt wird. Aber wenn ich den Loop auskommentiere, funktioniert das Setzen des Titels des RootWindows nicht mehr..
Lies mal dort: https://www.x.org/archive/X11R7.5/doc/m ... ync.3.html
The XFlush function flushes the output buffer. Most client applications need not use this function because the output buffer is automatically flushed as needed by calls to XPending,

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C: fifo lesen

Beitrag von Meillo » 25.08.2018 07:39:51

Das hier finde ich ein schoenes Beispiel fuer bessere Verstaendlichkeit mit `!' statt explizitem Vergleich:
RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
24.08.2018 20:55:13

Code: Alles auswählen

[...]
static int finish;

static void
term_hdl (int signum)
{
	/* if we do not use signum, gcc complains */
	if (signum == SIGTERM) {
		finish = 1;
	}
}

int
main(void)
{
[...]
	while (finish == 0) {
[...]
Wenn ich ``while finish gleich null'' lese, dann muss ich in meinem Kopf immer erst um eine Ecke denken, waehrend ``while not finish(ed)'' direkt 1:1 ausdrueckt was gemeint ist.
Use ed once in a while!

eggy
Beiträge: 3331
Registriert: 10.05.2008 11:23:50

Re: C: fifo lesen

Beitrag von eggy » 25.08.2018 09:09:45

Oder Variabkenname/Werte umdrehen und "while (unfinished)".

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C: fifo lesen

Beitrag von Meillo » 25.08.2018 09:56:48

eggy hat geschrieben: ↑ zum Beitrag ↑
25.08.2018 09:09:45
Oder Variabkenname/Werte umdrehen und "while (unfinished)".
Damit muss man vorsichtig sein. Negationen sind immer schwerer zu verstehen als die poitiven Gegenstuecke. Wenn man schon mit negierten Variablennamen anfaengt, dann ist die Wahrscheinlichkeit fuer schwer verstehbare boolsche Ausdruecke hoeher. Im konkreten Fall macht es vielleicht keinen Unterschied, im vielen anderen Faellen schon.
Use ed once in a while!

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: C: fifo lesen

Beitrag von RobertDebiannutzer » 25.08.2018 13:53:51

while (please_set_this_integer_to_one_if_you_like_to_break_the_while_loop) 8)

@bluestar: Ah ok. Ich habe es mal ohne loop versucht, nur mit einem Aufruf von XPending. Funktioniert. Aber was mich verwirrt:
The XPending function returns the number of events that have been received from the X server but have not been removed from the event queue.
Quelle: https://www.x.org/archive/X11R7.5/doc/m ... ync.3.html

Dieser int ist in meinem Programm immer 0*. Wenn es aber nur um die events ginge, die von meinem Programm ausgehen, könnte ich ja das XPending auch an den Schluss des loops stellen (nach XStoreName)?

Aber wie ist das jetzt mit den aufstauenden Events? Ich blicke bei diesem X immer noch nicht durch... :?

*Mein printf-Debugging (Code ist unten):

Code: Alles auswählen

Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before continue.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before read.
After read.
Before XStoreName.
After XStoreName.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
After select.
Before continue.
Before XPending.
value of tmp_int is 0.
After XPending.
Before select.
signal handler
After select.
Before error.
select: Interrupted system call
After error.
Before end.
After end.

Code: Alles auswählen

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <X11/Xlib.h>

/* BEGIN: user configuration */
static const char program_name[] = "myxd";
/* static const char fifo[] = "/tmp/dwmblocks_fifo_intern"; */
static const char fifo[] = "/home/user/fifo";
/* END: user configuration */

static int finish;

static void
term_hdl (int signum)
{
	/* if we do not use signum, gcc complains */
	if (signum == SIGTERM) {
		finish = 1;
		printf("signal handler\n");
	}
}

int
main(void)
{
	static char *display_name = NULL;
	static char name[BUFSIZ];

	static int fd;
	static int rc;
	static int screen;
	static int state = EXIT_SUCCESS;
	static Window root;

	static Display *dpy;
	static struct sigaction term_act;
	static struct timeval tv;
	/* static XEvent ev; */

	fd_set rfds; /* fixed size buffer */

	memset(&term_act, 0, sizeof(term_act));
	term_act.sa_handler = term_hdl;
	if (sigaction(SIGTERM, &term_act, NULL) < 0) {
		perror("sigaction");
		exit(EXIT_FAILURE);
	}

	dpy = XOpenDisplay(display_name);
	if (dpy == NULL) {
		fprintf(stderr, "%s:  unable to open display '%s'\n",
				program_name, XDisplayName(display_name));
		exit(EXIT_FAILURE);
	}
	root = RootWindow(dpy, screen);

	fd = open(fifo, O_RDWR | O_NONBLOCK);
	if (fd == -1) {
		perror("open");
		XCloseDisplay(dpy);
		exit(EXIT_FAILURE);
	}

	while (finish == 0) {
		printf("Before XPending.\n");
		int tmp_int = XPending(dpy);
		printf("value of tmp_int is %d.\n", tmp_int);
		printf("After XPending.\n");
		FD_ZERO(&rfds);
		FD_SET(fd, &rfds);
		tv.tv_sec = 5;
		tv.tv_usec = 0;
		printf("Before select.\n");
		rc = select(fd + 1, &rfds, NULL, NULL, &tv);
		printf("After select.\n");
		if (rc > 0) { /* success */
			memset(name, 0, sizeof(name));
			printf("Before read.\n");
			ssize_t got = read(fd, name, sizeof(name)-sizeof(char));
			printf("After read.\n");
			if (got < 0) {
				perror("read");
				state = EXIT_FAILURE;
				break;
			} else if (got == 0) {
				printf("EOF\\n");
				break;
			} else {
				/* remove trailing newline */
				if ((*name) && (name[strlen(name)-1] == '\n')) {
					name[strlen(name)-1] = '\0';
				}
				printf("Before XStoreName.\n");
				XStoreName(dpy, root, name);
				printf("After XStoreName.\n");
			}
		} else if (rc == 0) { /* timeout expired */
			printf("Before continue.\n");
			continue;
			printf("After continue.\n");
		} else { /* error */
			printf("Before error.\n");
			perror("select");
			state = EXIT_FAILURE;
			printf("After error.\n");
			break;
		}
	}
	printf("Before end.\n");
	close(fd);
	XCloseDisplay(dpy);
	printf("After end.\n");
	exit(state);
}

Benutzeravatar
bluestar
Beiträge: 2334
Registriert: 26.10.2004 11:16:34
Wohnort: Rhein-Main-Gebiet

Re: C: fifo lesen

Beitrag von bluestar » 25.08.2018 13:57:06

Starte mal dein Programm, setze den Fokus auf das Fenster und drück mal ne Taste, dann sollte ein Event bei dir ankommen, natürlich in der Version mit dem while(...) loop.

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: C: fifo lesen

Beitrag von RobertDebiannutzer » 25.08.2018 14:21:02

loop:

Code: Alles auswählen

		printf("Before XPending.\n");
		while (XPending(dpy)) {
			printf("Before XNextEvent.\n");
			XNextEvent(dpy, &ev);
			printf("After XNextEvent.\n");
		}
		printf("After XPending.\n");
Im Terminal ausgeführt und Tasten gedrückt (immer in den 5sec-Pausen zwischen "Before select" und "After select"):

Code: Alles auswählen

Before XPending.
After XPending.
Before select.
jifwjfiAfter select.
Before continue.
Before XPending.
After XPending.
Before select.
jiosjjioAfter select.
Before continue.
Before XPending.
After XPending.
Before select.
jiofjdsioAfter select.
Before continue.
Before XPending.
After XPending.
Before select.
jsdjoAfter select.
Before continue.
Before XPending.
After XPending.
Before select.
^C
?

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: C: fifo lesen

Beitrag von RobertDebiannutzer » 25.08.2018 17:06:35

@bluestar:
Mir ist gerade aufgefallen, dass es vielleicht ein Missverständnis gab. Du schreibst:
bluestar hat geschrieben: ↑ zum Beitrag ↑
25.08.2018 13:57:06
Starte mal dein Programm, setze den Fokus auf das Fenster [...]
Ich dachte, Du meinst mit dem Fenster das Fenster des Terminal Emulators (also in meinem Fall urxvt). Aber meintest Du vielleicht, dass mein Programm ein eigenes Fenster startet? Dem ist nicht so, denn es dient ja nur als "daemon" im Hintergrund zum Setzen des Titels des RootWindows, wobei es den entsprechenden string immer über die fifo erhält. Hintergrund ist, dass ich mittlerweile dwm einsetze (https://dwm.suckless.org). Die statusbar von dwm zeigt immer den Titel des RootWindows an:
dwm reads from the root window’s name to print arbitrary status text (like the date, load, battery charge). That’s much simpler than larsremote, wmiir and what not…
Quelle: obiger Link
Ich wollte nur nochmal darauf hinweisen, damit Du und andere Leser nochmal genau wissen, worum es geht. (@meillo kennt dwm ja eh).
Mein Programm ist quasi wie der Befehl "xsetroot -name", nur als daemon.

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C: fifo lesen

Beitrag von Meillo » 27.08.2018 09:51:15

Update:
RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
22.08.2018 15:46:39
Übrigens, die Videos in dem Link http://ulm.ccc.de/ChaosSeminar/2010/03_UnixPhil gibt's nicht mehr...
Der Ulmer CCC hat in letzter Zeit an seinem Server rumgeschraubt, dabei ist die Videoeinbindung kaputt gegangen. Jetzt sind die Videos aber wieder da.

Und falls es mal wieder nicht mehr gehen sollte, hier finden sie sich auch: http://ftp.ccc.de/regional/ulm/chaosseminar/
Use ed once in a while!

Benutzeravatar
bluestar
Beiträge: 2334
Registriert: 26.10.2004 11:16:34
Wohnort: Rhein-Main-Gebiet

Re: C: fifo lesen

Beitrag von bluestar » 28.08.2018 15:06:23

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
25.08.2018 14:21:02
Im Terminal ausgeführt und Tasten gedrückt (immer in den 5sec-Pausen zwischen "Before select" und "After select"):
Das ist ja auch absolut korrekt, da dein Select Timeout 5 Sekunden beträgt.
RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
25.08.2018 17:06:35
Ich dachte, Du meinst mit dem Fenster das Fenster des Terminal Emulators (also in meinem Fall urxvt). Aber meintest Du vielleicht, dass mein Programm ein eigenes Fenster startet? Dem ist nicht so, denn es dient ja nur als "daemon" im Hintergrund zum Setzen des Titels des RootWindows, wobei es den entsprechenden string immer über die fifo erhält. Hintergrund ist, dass ich mittlerweile dwm einsetze (https://dwm.suckless.org). Die statusbar von dwm zeigt immer den Titel des RootWindows
[...]
Dann solltest du auf jeden Fall mach recherchieren, ob bei deinem Programm überhaupt XEvents ankommen können, da bin ich überfragt... Falls nicht schenke dir den XPending() loop und nutze einfach XFlush(...) nach StoreName(...). In dem Falle kannst du auch von den Low-Level Funktionen "select(...)" und "read(...)" auf fopen und fgets umsteigen.

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: C: fifo lesen

Beitrag von RobertDebiannutzer » 29.08.2018 08:59:26

Also nach meinen Experimenten erhält mein Programm keine Events von X. Wäre ja auch seltsam...
Mit XFlush funktioniert es jedenfalls bestens.
Ich habe es sogar noch geschafft, die "interrupted system call"-Meldung zu unterdrücken, wenn das Programm mit (p)kill (also SIGTERM) geschlossen wird.
Ich habe herausgefunden, dass für die Fehlermeldung der Fehler "EINTR" verantwortlich ist.
Aus "man errno":
EINTR Interrupted function call (POSIX.1); see signal(7).
Aus "man 7 signal":
If a blocked call to one of the following interfaces is interrupted by a signal handler, then the call will be automatically restarted after the signal handler returns if the SA_RESTART flag was used; otherwise the call will
fail with the error EINTR:
Nun lasse ich perror() einfach nur im Fall ausführen, dass errno nicht EINTR ist. Aber soll ich dann im Fall, dass errno gleich EINTR ist, den exit-state auf EXIT_SUCCESS setzen und nur im Fall errno != EINTR den exit-state auf EXIT_FAILURE setzen? Wie sind denn da die Konventionen?

Code: Alles auswählen

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <errno.h>

/* BEGIN: user configuration */
static const char program_name[] = "myxd";
/* static const char fifo[] = "/tmp/dwmblocks_fifo_intern"; */
static const char fifo[] = "/home/user/fifo";
/* END: user configuration */

static int finish;

static void
term_hdl (int signum)
{
	/* if we do not use signum, gcc complains */
	if (signum == SIGTERM) {
		finish = 1;
	}
}

int
main(void)
{
	static char *display_name = NULL;
	static char name[BUFSIZ];

	static FILE *in;

	static int screen;
	static int state = EXIT_SUCCESS;
	static Window root;

	static Display *dpy;
	static struct sigaction term_act;

	memset(&term_act, 0, sizeof(term_act));
	term_act.sa_handler = term_hdl;
	if (sigaction(SIGTERM, &term_act, NULL) < 0) {
		perror("sigaction");
		exit(EXIT_FAILURE);
	}

	dpy = XOpenDisplay(display_name);
	if (dpy == NULL) {
		fprintf(stderr, "%s:  unable to open display '%s'\n",
				program_name, XDisplayName(display_name));
		exit(EXIT_FAILURE);
	}
	root = RootWindow(dpy, screen);

	in = fopen(fifo, "r+");
	if (in == NULL) {
		perror("fopen");
		XCloseDisplay(dpy);
		exit(EXIT_FAILURE);
	}

	while (finish == 0) {
		if (fgets(name, sizeof(name), in) == NULL) {
			if (errno != EINTR) {
				perror("fgets");
			}
			state = EXIT_FAILURE;
			break;
		} else {
			/* remove trailing newline */
			if ((*name) && (name[strlen(name)-1] == '\n')) {
				name[strlen(name)-1] = '\0';
			}
			XStoreName(dpy, root, name);
			XFlush(dpy);
		}
	}
	fclose(in);
	XCloseDisplay(dpy);
	exit(state);
}

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C: fifo lesen

Beitrag von Meillo » 29.08.2018 09:28:51

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
29.08.2018 08:59:26

Code: Alles auswählen

	while (finish == 0) {
		if (fgets(name, sizeof(name), in) == NULL) {
			if (errno != EINTR) {
				perror("fgets");
			}
			state = EXIT_FAILURE;
			break;
		} else {
			/* remove trailing newline */
			if ((*name) && (name[strlen(name)-1] == '\n')) {
				name[strlen(name)-1] = '\0';
			}
			XStoreName(dpy, root, name);
			XFlush(dpy);
		}
	}
}
Ich finde, dass weniger Einrueckungen oft mit besserem Code korrelieren.

Ein gutes Schema finde ich, zuerst alle Fehlerfaelle einzeln auszusortieren und anschliessend den eigentlichen Code auszufuehren.

Jedenfalls sollte man es vermeiden, den eigentlichen Code in lauter Positiv-Bedingungen tief einzuschachteln, weil das beim Lesen sehr viel mehr ``Stack-Space'' braucht.

Darum: Je weniger tief geschachtelt, desto weniger Stack-Space im Gehirn noetig (im Klartext: Man muss sich weniger State merken), desto einfacher verstaendlicher Code, desto weniger Fehler ... und das alles laesst sich einfach ueber die Einrueckungstiefen des Codes ablesen.

(Falls man uebrigens mit breaks und continues nicht recht weiter kommt und meint, gotos zu brauchen, dann ist das ein Zeichen dafuer, dass man Codeteile in eigene Funktionen outfactoren sollte, weil man dann mit returns arbeiten kann.)


Somit also mein Vorschlag (bezogen auf diesen einen Aspekt) statt obigem Code:

Code: Alles auswählen

	while (finish == 0) {
		if (fgets(name, sizeof(name), in) == NULL) {
			if (errno != EINTR) {
				perror("fgets");
			}
			state = EXIT_FAILURE;
			break;
		}
		/* remove trailing newline */
		if ((*name) && (name[strlen(name)-1] == '\n')) {
			name[strlen(name)-1] = '\0';
		}
		XStoreName(dpy, root, name);
		XFlush(dpy);
	}
}
Use ed once in a while!

inne
Beiträge: 3273
Registriert: 29.06.2013 17:32:10
Lizenz eigener Beiträge: GNU General Public License
Kontaktdaten:

Re: C: fifo lesen

Beitrag von inne » 29.08.2018 09:50:17

Meillo hat geschrieben: ↑ zum Beitrag ↑
29.08.2018 09:28:51

Ich finde, dass weniger Einrueckungen oft mit besserem Code korrelieren.
OT: Ist das mit "Soweit srechtlinks wie möglich" Programmieren gemeint? Das las ich mal in einer Vorgabe für C-Programmierer..

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C: fifo lesen

Beitrag von Meillo » 29.08.2018 14:42:44

inne hat geschrieben: ↑ zum Beitrag ↑
29.08.2018 09:50:17
Meillo hat geschrieben: ↑ zum Beitrag ↑
29.08.2018 09:28:51

Ich finde, dass weniger Einrueckungen oft mit besserem Code korrelieren.
OT: Ist das mit "Soweit srechtlinks wie möglich" Programmieren gemeint? Das las ich mal in einer Vorgabe für C-Programmierer..
Vermutlich ist das damit gemeint.

Man darf diese Stilregeln nicht zu starr auslegen, sie helfen einem aber, zu erkennen, welche Stellen im Code man sich mal genauer anschauen sollte, weil dort vermutlich Refactoringpotenzial vorhanden ist. Darueber hinaus sind das eigentlich Wertvolle die Gedankenwege dahinter. Darum versuche ich diese bei meinem Kommentaren hier auch immer darzulegen. Zu verstehen und bewusst begruendet zu entscheiden ist das Wichtigste!
Use ed once in a while!

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: C: fifo lesen

Beitrag von RobertDebiannutzer » 01.09.2018 14:25:15

@meillo: Gute Anregung, danke!

Dann ist mein Programm ja soweit fertig, herzlichen Dank für eure Hilfe! :THX:
Auf "[gelöst]" setze ich den Thread, wenn ich noch beweiskräftige Dokumentation zu XFlush gefunden habe.

Aber XFlush kommt mir von der Logik her sowieso richtig vor, nachdem ich gerade ein weiteres kleines C-Programm für einen anderen Zweck geschrieben habe. Dieses Programm hört eine Pipe ab und gibt den Input an stdout weiter, wenn er einem bestimmten Muster entspricht. Der Output soll dann durch einen shell-while-loop abgearbeitet werden. Dies soll aber nicht erst geschehen, wenn sich das Programm beendet, sondern Zeile für Zeile!
Somit funktioniert "programm | while read line; do something with $line; done" nicht, wenn das Programm den output mittels printf abgibt. Es funktioniert aber schon, wenn hinter das printf ein "fflush(stdout);" geschaltet ist. (Das hat damit zu tun, das stdout nur line-buffered ist, wenn der Output an ein Terminal geht. Wenn er aber in eine Pipe geht, ist stdout nicht line-buffered. Das muss man erstmal wissen... 8O ). Naja, jedenfalls scheint ja dieses "Output-flushen" auch für standard i/o common practice zu sein, also warum nicht auch beim Xserver?

OT: Weiter vorne im Thread hatte ich ein Stück eines Shell-Scriptes gepostet, wo einfach der Inhalt einer Datei ungeprüft ausgeführt wurde. Das habe ich natürlich noch geändert. Schließlich will ich ja keinen "good-faith-code" Code schreiben ...

Antworten