Server-Client-Anwendung friert gelegentlich bei Nachrichtenübermittlung via SIGUSR1 und SIGUSR2 komplett ein



  • Hi, ich hab hier eine kleine "Client-Server-Anwendung" geschrieben. Der Server wird zu erst gestartet und gibt seine eigene PID (ProzessID) aus und wartet auf Nachrichten vom Client, die er ausgeben kann. Die Server-PID erhält der Client beim Aufruf als Parameter. Gleichzeitig wird dem Client auch eine beliebige lange Nachricht übergeben. Eine 1000 Zeichen lange Nachricht habe ich mit Hilfe dieses Blindtextgenerators generiert. Der Client wird mehrfach gestartet und es wird mehrfach eine Nachricht an den Server gesendet.

    Die ganze Nachrichtenübermittlung geschieht via Systemcalls SIGUSR1 und SIGUSR2. Die Nachricht wird binär vom Client an den Server gesendet. Der Server bestätigt JEDES eintreffende Signal mit einem SIGUSR1 an den Client. Erst nach der Bestätigung sendet der Client das nächste Signal los. Mit dem Bestätigen des Signals möchte ich sicherstellen, dass die Verarbeitung des Signals am Server beendet ist, bevor der Client das nächste Signal ("bit") an den Server sendet.

    Ich habe jetzt das Problem, dass die Anwendung schon funktioniert, aber leider nicht zuverlässig und ich bin ratlos woran das liegen kann. Ab und an friert einfach alles ein. Das kann bei der ersten Nachricht passieren, genauso wie erst bei der Dritten. Wenn ich usleep() hoch setze , dann scheint es zuverlässiger zu werden.. Eventuell hat es mit dem Linux bzw. dem Kernel etwas zu tun.

    Ich programmiere noch nicht so lange, daher würde ich mich als Anfänger bezeichnen. Falls ihr irgendwelche Ideen oder Vermutungen habt, dann einfach posten. Mir kann womöglich alles weiterhelfen und ich bin für jede Hilfe dankbar!

    Die Anwendung ist eine Aufgabe, an der ich arbeite und folgendes durfte ich verwenden:
    ◦ write
    ◦ printf
    ◦ signal
    ◦ sigemptyset
    ◦ sigaddset
    ◦ sigaction
    ◦ kill
    ◦ getpid
    ◦ malloc
    ◦ free
    ◦ pause
    ◦ sleep
    ◦ usleep
    ◦ exit
    ◦ SIGUSR1 and SIGUSR2.

    server.c:

    #include "minitalk.h"
    
    void	sighandler(int signum, siginfo_t *info, void *context UTILS_UNUSED)
    {
    	static char	a = 0;
    	static int	bits = 8;
    
    	if (signum == SIGUSR1)
    		a |= 1;
    	if (--bits > 0)
    		a <<= 1;
    	else
    	{
    		write(1, &a, 1);
    		bits = 8;
    		a = 0;
    	}
    	usleep(10);
    	kill(info->si_pid, SIGUSR1);
    }
    
    int	main(void)
    {
    	struct sigaction sa;
    	pid_t	pid;
    
    	sigfillset(&sa.sa_mask);
    	sa.sa_sigaction = sighandler;
    	sa.sa_flags = SA_SIGINFO | SA_RESTART;
    	pid = getpid();
    	printf("%d\n", pid);
    	if (sigaction(SIGUSR1, &sa, NULL) == -1 ||
    		sigaction(SIGUSR2, &sa, NULL) == -1)
    			perror("SIGACTION");
    	while (1)
    		pause();
    	return (0);
    }
    

    client.c:

    #include "minitalk.h"
    
    void	sighandler(int signum UTILS_UNUSED, siginfo_t *info UTILS_UNUSED,
    		void *context UTILS_UNUSED)
    {
    	;
    }
    
    void	send_char_via_sig(char a, int bits, int pid)
    {
    	while (bits-- > 0)
    	{
    		if (a & 128)
    			kill(pid, SIGUSR1);
    		else
    			kill(pid, SIGUSR2);
    		pause();
    		a <<= 1;
    		usleep(10);
    	}
    }
    
    void	send_str_via_sig(char *str, int pid)
    {
    	int	i;
    
    	i = 0;
    	while (str[i])
    		send_char_via_sig(str[i++], 8, pid);
    }
    
    int	main(int argc, char *argv[])#ifndef MINITALK_H
    # define MINITALK_H
    
    # include <signal.h>
    # include <unistd.h>
    # include <stdlib.h>
    # include <stdio.h>
    # define UTILS_UNUSED __attribute__((unused))
    
    void	sighandler(int signum, siginfo_t *info, void *context);
    void	send_char_via_sig(char a, int bitwidth, int pid);
    void	send_str_via_sig(char *str, int pid);
    #endif
    {
    	struct sigaction sa;
    
    	sigfillset(&sa.sa_mask);
    	sa.sa_sigaction = sighandler;
    	sa.sa_flags = SA_SIGINFO | SA_RESTART;
    	if (sigaction(SIGUSR1, &sa, NULL) == -1)
    		perror("SIGACTION");
    	if (argc != 3)
    		return (0);
    	send_str_via_sig(argv[2], atoi(argv[1]));
    	return (0);
    }
    

    minitalk.h:

    #ifndef MINITALK_H
    # define MINITALK_H
    
    # include <signal.h>
    # include <unistd.h>
    # include <stdlib.h>
    # include <stdio.h>
    # define UTILS_UNUSED __attribute__((unused))
    
    void	sighandler(int signum, siginfo_t *info, void *context);
    void	send_char_via_sig(char a, int bitwidth, int pid);
    void	send_str_via_sig(char *str, int pid);
    #endif
    

Anmelden zum Antworten