View Full Version : dubbi sul pause()...sotto unix
ragazzi non riesco a capire bene l utilizzo di questa funzione:quando metto un processo in pause, esso dovrebbe risvegliarsi alla ricezione di un segnale gestito da un apposita funzione ad esempio:
//da processo 1
...
signal(SIGUSR1,sveglio);
pause();
...
//da altro processo
...
kill(processo1,SIGUSR1);
...
//il sig_handler
...
void sveglio()
{
printf("mi sveglio\n");
return;
}
va bene cosi?dovrebbe ripartire il padre dove si era fermato? il fatto è che non sempre si sveglia...ad esempio, può succedere che quando va di nuovo in pausa nn si risveglia più!
c è qualcuno che può aiutarmi?
ilsensine
06-12-2004, 22:04
Posta un programmino completo e compilabile che consente di riprodurre il problema.
http://forum.hwupgrade.it/showthread.php?s=&threadid=828647
una domandina facile facile...ma per fare ping pong tra due processi mi conviene usare i segnali? o meglio se faccio waitpid con un uso opportuno?
per farla semplice non funziona neanche questo:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void sveglio()
{
printf("sveglia\n");
// raise(SIGCONT);
}
int main(){
int figlio;
signal(SIGUSR1,sveglio);
printf(" proviamo i pause, se arrivo alla fine allora funge altrimenti uccidere con ctrl+c\n");
figlio=fork();
if (figlio==0){
pause();
kill(getppid(),SIGUSR1);
pause();
kill(getppid(),SIGUSR1);
pause();
exit(0);
}else{
sleep(1);
kill(figlio,SIGUSR1);
pause();
kill(figlio,SIGUSR1);
pause();
kill(figlio,SIGUSR1);
waitpid(figlio,NULL,NULL);
printf("finito\n");
}
}
ilsensine
07-12-2004, 07:42
Qui funziona, ma per pura fortuna.
Il programma è suscettibile di una ovvia race condition se avviene un context switch tra una kill() e la successiva pause(): in questa situazione, un processo esegue una kill mentre l'altro ancora non è nello stato di pause, rendendo la kill totalmente inefficace. Posso simulare la race inserendo una sched_yield() tra una kill e la pause successiva.
ilsensine
07-12-2004, 07:47
In parole povere:
p1 p2
pause
(switch su p2)
kill
(switch su p1??)
kill
pause
pause
bye
Se questo capita, la race esplode. Dipende dallo scheduler se dopo le kill avviene il context switch o meno, sono liberi di decidere di farlo oppure no.
in poche parole per far funzionare il ping pong fra i processi devo inserire degli sleep in modo tale da sincronizzare i due processi?...i
ilsensine
07-12-2004, 08:57
Il problema è concettuale, non tanto implementativo. Il tuo errore è eseguire la kill senza essere sicuro dello stato in cui si trova l'altro processo. Visto che l'esecuzione è totalmente asincrona, non puoi essere sicuro dello stato in alcun modo ovvio.
Se vuoi fare un semplice ping-pong, usa i messaggi (msgsnd/msgrcv).
il problema è che questo esercizio è relativo alla parte di sistemi operativi mod a...quindi nello scritto nn posso usare nozioni di sistemi b...noi facciamo l IPC V solo al secondo modulo...
devo passare lo scritto di mod a ma nel frattempo sto seguendo il b all università....
perciò posso usare solo segnali, wait....capito?
ho provato ad usare delle sleep opportunamente messe e va tipo prima dei kill in modo tale che l altro processo vada in pause quando deve. E' sporco come metodo? considerando che i cambi di contesti avvengono sempre negli ordini di ms 1 secondo nella sleep è più che sufficiente non credi?
fammi sapere
ciao e grazie
P.S. scusa per il disturbo!!!
ilsensine
07-12-2004, 10:16
Originariamente inviato da Ricky
E' sporco come metodo?
E' più che sporco, è sbagliato per i motivi che ti ho detto.
Una soluzione più pulita (relativamente) può essere questa: imponi che, quando viene svegliato da kill, il processo invii un feedback a chi lo ha svegliato (ad es. tramite SIGUSR2). Se il feedback non arriva entro un certo timeout, ritenti il primo kill.
ilsensine
07-12-2004, 10:35
Qualcosa di questo tipo insomma: (negherò fino alla morte di aver scritto questa porcheria :D)
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
int killing;
void sveglio()
{
printf("sveglia\n");
}
void ack()
{
killing = 0;
}
void do_kill(pid_t pid)
{
killing = 1;
while(killing)
{
kill(pid, SIGUSR1);
// Se SIGUSR2 arriva durante usleep, questa si interrompe con EINTR
if(killing)
usleep(25000);
}
}
int main(){
int figlio;
signal(SIGUSR1,sveglio);
signal(SIGUSR2,ack);
printf(" proviamo i pause, se arrivo alla fine allora funge altrimenti uccidere con ctrl+c\n");
figlio=fork();
if (figlio==0){
pause();
kill(getppid(), SIGUSR2);
do_kill(getppid());
pause();
kill(getppid(), SIGUSR2);
do_kill(getppid());
pause();
kill(getppid(), SIGUSR2);
exit(0);
}else{
sleep(1);
do_kill(figlio);
pause();
kill(figlio, SIGUSR2);
do_kill(figlio);
pause();
kill(figlio, SIGUSR2);
do_kill(figlio);
waitpid(figlio,NULL,0);
printf("finito\n");
}
}
secondo me la tua versione non è poi tanto diversa da quella con degli sleep opportunamente messi, in quanto a me gli sleep li fa sempre mentre a te solo nel caso in cui ti trovi a mandare il segnale prima che va in pause....giusto?
ti faccio vedere una mia versione funzionante anche se sporchissima!:):)
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
void sveglio()
{
printf("sveglia\n");
// raise(SIGCONT);
}
int main(){
int figlio;
signal(SIGUSR1,sveglio);
printf(" proviamo i pause, se arrivo alla fine allora funge altrimenti uccidere con ctrl+c\n");
figlio=fork();
if (figlio==0){ //temporalmente(Sequenze)
pause(); /* 1 */
sleep(1); /* 3 */ //aspetto il padre(pause)
kill(getppid(),SIGUSR1); /* 4 */
pause(); /* 5 */
sleep(1); /* 6 */
kill(getppid(),SIGUSR1); // e via dicendo
pause();
exit(0);
}else{
sleep(1);
kill(figlio,SIGUSR1); /* 2 */
pause(); /* 3 */ //assicurato dallo sleep
sleep(1); /* 5 */
kill(figlio,SIGUSR1); /* 6 */
pause();
sleep(1);
kill(figlio,SIGUSR1);
waitpid(figlio,NULL,NULL);
printf("finito\n");
exit(0);
}
}
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.