[c++/Linux] Program uruchomiony w tle (i jego restart)

0

Hej. Może będzie ktoś w stanie pomóc.
Mam własny program, który co sek. (w środku jest pauza w pętli) sprawdza zawartość jakiegoś pliku i na jej podstawie zapisuje coś w innym pliku. Jeśli uruchomiony jest na pierwszym planie, to plik jest sprawdzany i wynik zapisywany. Jeśli jednak uruchomię go w tle, to jest tak, jakby nie działał. Jaka może być tego przyczyna?
Chciałbym też, by ten program sprawdzał, czy nie zmieniła się jego wersja binarna (nie został przekompilowany). Jeśli się zmieniła, to powinien uruchomić nowy proces siebie i zabić proces działający do tej chwili. Nie mam pomysłu na to. Wydaje mi się, że jeśli uruchomię coś poprzez komendę "system()", to będzie to dziecko procesu, który je wywołał i jak ten proces wywołujący się zakończy, to jego dzieci też.
Z góry dzięki za jakąkolwiek pomoc.

0

Co do 2'giej czesci pytania:

Proces mozna by wystartowac fork'iem() zamiast system() i odlaczyc (detach) go od glownego procesu.
Binarna wersje moznaby sprawdzic suma kontrolna (crc8/16/32... lub md5 lub innym bardziej skomplikowanym algorytmem sha1/2/3), na inicjalizacji liczysz sume binarki, potem co jakis czas sprawdzasz (a zeby nie liczyc niepotrzebnie mozna sprawdzac czas updatu pliku i w razie jakby sie zmienil ponownie przeliczyc sume kontrolna)
(aczkolwiek system("nohup proc.exe &") powinien tez zadzialac i bez problemu odlaczyc sie od parenta)

Co do pierwszej nie jestem pewnien ale nie powinno byc problemow chyba ze gdzies kozystasz z stdin lub out i masz cos przekierowane na /dev/null - ale strzelam na slepo

pzdr

0

Dzięki za wskazówkę dotyczącą fork'a. Sprawdzę to.
Nie korzystam z stdin ani stdout. Uruchomiony program nie wymaga żadnej ingerencji z zewnątrz, by w jakimkolwiek momencie kontynuować swą pracę.

0

funkcje sprawdzajaca sume i odpalajaca nowy proces obsluguj poprzez sygnal, najlepiej SIGUSR1 lub 2 albo SIGHUP
np.: USR1 jako warunkowe jeśli suma sie zmieniła, a USR2 jako bezwzględne, niezależnie od tego czy suma się zgadza czy nie.

Nie może byc tak, że program przeładowyje sie sam w przypadku każdej kompilacji, bo może sie zdarzyc tak, że będziesz świadomie kompilował kod, w którym są gdzie indziej błędy, kod się skompiluje a program działać nie musi.

przejście do tła załatwiasz forkiem, rodzica konczysz, dziecko zostawiasz, odpalenie nowego procesu załatwiasz poprzez execve czy execvp albo pochodne, te funkcje kończą jednocześnie proces wywołujący je.

Nie używaj nigdy system() a zwłaszcza, gdy proces ma pracować z konta roota, przejęcie kontroli nad systemem jest wtedy bajecznie łatwe.

forkowanie do tła wykonujesz mniej więcej tak:

  pid_t pd=fork();
  if(pd==-1){
    perror("fork - error");
    return -1;        
  }
  if(pd)return 0;  // parent exits.
  setsid();
  chdir("/"); // albo "/tmp"
  int i=getdtablesize();      // dzast in kejs
  while(i--)close(i); // zamkniecie wszystkich otwartych plikow; 0 - stdin, 1 - stdout, 2 - stderr, wyzsze to juz inne pliki

albo uzyc gotowej funkcji daemon(), ktora dodatkowo otwiera /dev/null dla stdin, stdout i stderr, ale chyba nie zamyka reszty plikow.

tu wrzuciłem funkcje tworzace srodowisko i listy parametrow dla exec...()

0

Załatwiłem tak przeładowywanie się po kompilacji:

		// (...)
//		cout << "Working in background..." << endl;
		struct stat attrib;
		struct tm *clock;
		stat(argv[0], &attrib);
		clock = gmtime(&(attrib.st_mtime));
		int last_compile;
		last_compile = attrib.st_mtime;

		do {
			// (...)
			sleep(1);

			stat(argv[0], &attrib);
			clock = gmtime(&(attrib.st_mtime));
			if (last_compile != attrib.st_mtime) {
				cout << "Restart!!!" << endl;
//				sleep(1);
				execl(argv[0], argv[0], argv[1], argv[2], argv[3], 0);
			}

		} while(true);
		(...)

I działa dobrze - tak sądzę.
Nie wiem jednak, dlaczego uruchomienie programu w tle powoduje, iż on zawiesza pracę i dopiero przywrócenie go na pierwszy plan wznawia jego działanie [???]

0
flabra napisał(a)
  int i=getdtablesize();      // dzast in kejs
  while(i--)close(i); // zamkniecie wszystkich otwartych plikow; 0 - stdin, 1 - stdout, 2 - stderr, wyzsze to juz inne pliki

Ostatnio walczylem z problemem gdzie procesy potomne procesu startowanego przez CreateProcess pod winXP z domyslnymi parametrami (czyli np. przez komende "start xxx" ) nie pozwalaly na ponowny restart parenta jesli ten mial wczesniej otwarte porty.

W CreateProcess rozbija sie to o dziedziczenie portow od parenta.
I pytanie bo nie wnikalem w szczegoly, czy getdtablesize() zawiera tablice do wszystkich FD's ? (domniemam ze tak)
Czyli czy iterowanie po i ubije tez poloaczenia na portach w ten czy inny sposob (mniejsza o implementacje)

Wiec na linuxie moj problem bylby w ten sposob wlasnie rozwiazany.

Sory za oftopa,
Co do problemu z backgroundem sprawdze u siebie czy mam podobne zachowanie i dam odpowiedz.

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