Proces zombie po wysłaniu sygnału

0

Witam. Właśnie piszę program, który wysyła sygnał do procesu potomnego. Problem pojawia się jednak, gdy wysyłam np. sygnał nr 19. Proces potomny zostaje zatrzymany (ok), ale proces macierzysty nagle staje się procesem - zombie. Czy można temu jakoś zapobiec?

Kod:
a.c - wywoływany jako potomny:

#include <signal.h>
#include <sys/types.h>

int main(int argc, char* argv[])
{
	if (argc<3)
	{
		printf("Za mala liczba argumentow!\n");
		return 1;
	}

__sighandler_t obsluga;
	const int sig = atoi(argv[1]);
	const int arg2 = strtol(argv[2], NULL, 0);
	if(arg2==1)
	{
		obsluga=SIG_DFL;
		const __sighandler_t obsluga=obsluga;
	}
	else if(arg2==2)
	{
		obsluga=SIG_IGN;
		const __sighandler_t obsluga=obsluga;
	}
	else if(arg2==3)
	{
		printf("Wlasna obsluga sygnalu\n");
	}
	else printf("Nieprawidlowy sposob obslugi!\n");
	signal(sig, obsluga);

	pause();

return 0;
}

b.c:

#define _POSIX_SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc, char* argv[])
{
	if (argc<3)
	{
		printf("Za mala liczba argumentow!\n");
		return 1;
	}
	const int sig = atoi(argv[1]);

switch(fork())
	{
	case -1:
	  perror("Blad funkcji fork().\n");
	  exit(1);
	  break;
	case 0:
	  execl("./a.x", "a.x", argv[1], argv[2], NULL);
	  perror("Blad fukcji exec().\n"); 
	  _exit(2);
	  break;
	default:
	sleep(2);
		kill(getppid(), sig);
	  break;
	}

return 0;
1

UB w przypadku, gdy arg2 == 3 w a.c

Kolejny błąd: kill(getppid(), sig); - powinieneś wysłać sygnał do dziecka, a nie do rodzica rodzica :)

0

Mógłbyś wyjaśnić ten skrót?
Póki co nie podawałem 3 jako arg2. Własną obsługę sygnału zostawiłem na później.

1

Jasne: UB = undefined behaviour. Rejestrujesz obsługę sygnału na niezainicjalizowaną wartość, stąd UB - nie wiesz, co program zrobi jak dostanie sygnał. Zapewne w tym momencie się wywróci, ale nigdy nie możesz być pewny...

0

Jasne: UB = undefined behaviour.
Dzięki.

W tej chwili pracuję nad własną obsługą sygnału (prosta funkcja podająca PID, numer oraz nazwę sygnału). Niestety:

  1. Informacje nie zawsze się wypisują
  2. Numer sygnału jest błędny
  3. Nie mogę uzyskać nazwy sygnału (zamiast tego, np. dla wywołania ./b.x 2 3 otrzymuję prawidłowe PID, nr sygnału 65, a nazwę: InterruptZa mala liczba argumentow!)

Numer oraz nazwę sygnału muszą być wzięte z tablicy sys_siglist[] (musiałem ją zadeklarować ze względu na błąd kompilatora).

Poniżej kod:
a.c:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>

extern const char * const sys_siglist[];

void wlasna_obsluga(int sg)
{
	printf("PID: %d, Nr sygnalu: %d, Nazwa sygnalu: %s", getpid(), _NSIG, sys_siglist[sg]);
}

int main(int argc, char* argv[])
{
	if (argc<3)
	{
		printf("Za mala liczba argumentow!\n");
		return 1;
	}

	const int sig = atoi(argv[1]);
	const int arg2 = strtol(argv[2], NULL, 0);
	__sighandler_t obsluga;
	if(arg2==1)
	{
		obsluga=SIG_DFL;
		const __sighandler_t obsluga=obsluga;
	}
	else if(arg2==2)
	{
		obsluga=SIG_IGN;
		const __sighandler_t obsluga=obsluga;
	}
	else if(arg2==3)
	{
		wlasna_obsluga(sig);
	}
	else printf("Nieprawidlowy sposob obslugi!\n");
	signal(sig, obsluga);

	pause();

return 0;
}

b.c:

#define _POSIX_SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc, char* argv[])
{
	if (argc<3)
	{
		printf("Za mala liczba argumentow!\n");
		return 1;
	}
	const int sig = atoi(argv[1]);
	int pid;

switch(fork())
	{
	case -1:
	  perror("Blad funkcji fork().\n");
	  exit(1);
	  break;
	case 0:
		pid=getpid();
	  execl("./a.x", "a.x", argv[1], argv[2], NULL);
	  perror("Blad fukcji exec().\n"); 
	  _exit(2);
break;
	default:
	sleep(2);
		kill(pid, sig);
	 wait(0);
	  break;
	}

return 0;
}
1

To teraz przeanalizuj moje implementacje:
a.c:

#include <sys/types.h>

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

extern const char * const sys_siglist[];

void
wlasna_obsluga(int sg)
{
	printf("PID: %d, Nr sygnalu: %d, Nazwa sygnalu: %s\n", getpid(), sg,
		sys_siglist[sg]);
	exit(0);
}

int
main(int argc, char* argv[])
{
	if (argc < 3) {
		printf("Za mala liczba argumentow!\n");
		return 1;
	}

	const int sig = atoi(argv[1]);
	const int arg2 = atoi(argv[2]);
	__sighandler_t obsluga;

	if (arg2 == 1)
		obsluga = SIG_DFL;
	else if (arg2 == 2)
		obsluga = SIG_IGN;
	else if (arg2 == 3)
		obsluga = wlasna_obsluga;
	else
		printf("Nieprawidlowy sposob obslugi!\n");

	if (signal(sig, obsluga) == SIG_ERR) {
		printf("Nie moge zainstalowac obslugi sygnalu.\n");
		return 3;
	}

	while (1) {
		sleep(1);
	}

	return 0;
}

oraz b.c:

#define _POSIX_SOURCE

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>

int
main(int argc, char* argv[])
{
	pid_t pid;

	if (argc < 3) {
		printf("Za mala liczba argumentow!\n");
		return 1;
	}

	pid = fork();

	if (pid == -1) {
		perror("Blad funkcji fork().\n");
		return 1;
	} else if (pid == 0) {
		if (execl("./a.x", "a.x", argv[1], argv[2], NULL) == -1) {
			perror("Blad fukcji exec().\n");
			return 2;
		}
		/* NOTREACHED */
	}

	sleep(2);
	kill(pid, atoi(argv[1]));
	wait(NULL);

	return 0;
}

Dalej w swoim kodzie pobierałeś niezainicjalizowane wartości.

0

@kapojot - Wielkie dzięki za pomoc. Pewnie kombinowałbym jeszcze miesiąc, zanim odkryłbym, co jest nie tak.

1 użytkowników online, w tym zalogowanych: 0, gości: 1