Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Intervista a Stop Killing Games: distruggere videogiochi è come bruciare la musica di Mozart
Intervista a Stop Killing Games: distruggere videogiochi è come bruciare la musica di Mozart
Mentre Ubisoft vorrebbe chiedere agli utenti, all'occorrenza, di distruggere perfino le copie fisiche dei propri giochi, il movimento Stop Killing Games si sta battendo per preservare quella che l'Unione Europea ha già riconosciuto come una forma d'arte. Abbiamo avuto modo di parlare con Daniel Ondruska, portavoce dell'Iniziativa Europa volta a preservare la conservazione dei videogiochi
Samsung Galaxy S25 Edge: il top di gamma ultrasottile e leggerissimo. La recensione
Samsung Galaxy S25 Edge: il top di gamma ultrasottile e leggerissimo. La recensione
Abbiamo provato il nuovo Galaxy S25 Edge, uno smartphone unico per il suo spessore di soli 5,8 mm e un peso super piuma. Parliamo di un device che ha pro e contro, ma sicuramente si differenzia dalla massa per la sua portabilità, ma non senza qualche compromesso. Ecco la nostra prova completa.
HP Elitebook Ultra G1i 14 è il notebook compatto, potente e robusto
HP Elitebook Ultra G1i 14 è il notebook compatto, potente e robusto
Pensato per il professionista sempre in movimento, HP Elitebook Ultra G1i 14 abbina una piattaforma Intel Core Ultra 7 ad una costruzione robusta, riuscendo a mantenere un peso contenuto e una facile trasportabilità. Ottime prestazioni per gli ambiti di produttività personale con un'autonomia lontano dalla presa di corrente che permette di lavorare per tutta la giornata
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 25-12-2006, 10:16   #1
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
[C] Gestione dei segnali

Ciao e auguri a tutti

Volevo sapere se questa è una giusta gestione del segnale SIGINT, perché quando faccio partire il programma e premo CTRL-C mi va in segmentation fault e non riesco a capirne la causa. Questo è il codice del main (ancora provvisorio):

Codice:
#include "functions.h"

int main(void){

int i;
pid_t pid;
int status;
ssize_t nread;
ssize_t nwrite;
struct sigaction sigint_handl;
char *buf=(char *)malloc(sizeof(char)*COMM_LENGTH);
char *name=(char *)malloc(sizeof(char)*COMM_LENGTH);

sigint_handl.sa_handler=sigint_handler;

if (sigemptyset(&sigint_handl.sa_mask)!=0){
   perror("sigemptyset failed"); 
   exit(SIGH_ERR); 
}

sigint_handl.sa_flags=0;

if(sigaction(SIGINT,&sigint_handl,NULL)){
   perror("sigaction failed");
   exit(SIGH_ERR);

}

setjmp(chdir_return);
setjmp(sigint_return);
while(1){
   sprintf(buf,"%s $  ", get_current_dir_name());

   if ((nwrite=write(STDOUT_FILENO,buf,COMM_LENGTH)) != COMM_LENGTH){
      perror("write error");
      if (buf!=NULL){
         free(buf);
         buf=NULL;
      }
      if (name!=NULL){
         free(name);
         name=NULL;
      }
      exit(ERR_GEN);
   } 
   if( (nread = read(STDIN_FILENO,buf,COMM_LENGTH)) <= 0){

       perror("read error");
       if (buf!=NULL){
         free(buf);
         buf=NULL;
      }
      if (name!=NULL){
         free(name);
         name=NULL;
      }
      exit(ERR_GEN);
   }  

   strcpy(name,buf);
   parse(name);
   if(command_lines(name) == OK){
      if((pid=fork()) < 0){
         perror("fork error");
         if (buf!=NULL){
            free(buf);
            buf=NULL;
         }
         if (name!=NULL){
            free(name);
            name=NULL;
         }
         exit(FORK_ERR);
      }
      if(pid > 0){
         if (waitpid(pid,&status,0) == -1){
            perror("waitpid error");
            if (buf!=NULL){
               free(buf);
               buf=NULL;
            }
            if (name!=NULL){
               free(name);
               name=NULL;
            }
         }
      }
   }
} 
return 0;
}
E questo quello del signal handler:

Codice:
#include "functions.h"

void sigint_handler(int signo){
   if(signo != SIGINT){
      printf("Something wrong, handler for SIGINT");
      exit(SIGH_ERR);  
   }
   else
      longjmp(sigint_return,0);
}
Grazie e buon natale a tutti.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 25-12-2006, 11:03   #2
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Città: TO
Messaggi: 5206
Prendila come una mia opinione personale ... credo che non sia una buona idea mettere un longjmp() nell'handler.
__________________
Andrea, SCJP 5 (91%) - SCWCD 5 (94%)
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 09:48   #3
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Perché no? E come faccio a tornare qua "sprintf(buf,"%s $ ", get_current_dir_name());" (che sarebbe il prompt della shell)?
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 09:54   #4
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
In quel caso la read ritorna -1 con errno==EINTR.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 10:03   #5
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Ah quindi dovrei controllare se la read torna EINTR (e se lo torna lanciare il signal handler) ? Un'altra possibilità. Mettiamo il caso che io voglia eseguire ls e mi trovo in una directory con tantissimi files. L'esecuzione di ls non è istantanea ma ci mette un po' per listare tutto il contenuto. Mettiamo il caso che durante l'esecuzione di ls premo CTRL-C. Visto che ls lo dovrei eseguire tramite una exec (a meno di altri suggerimenti da parte vostra ) , come faccio a fargli eseguire il mio signal handler dato che la exec di un comando riporta a default il gestore del segnale?

Grazie.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 10:21   #6
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Non ti seguo... il segnale viene inviato al tuo processo, non a ls
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 10:31   #7
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Cerco di spiegarmi meglio. Io per eseguire un comando con questa shell (perché in realtà il programma che sto realizzando è una shell) creo un figlio tramite fork() e faccio eseguire al figlio un comando tramite exec(). Il figlio eredita dal padre il signal handler impostato da me, ma nel momento in cui eseguo la exec di un comando, il signal handler ritorna quello di default. Io vorrei fare in modo (se possibile) di eseguire il mio signal handler dopo la exec. Per questo ti avevo fatto l'esempio di ls all'interno di una directory con migliaia di files, perché ad esempio mi stufo di vedere tutto il contenuto e ad un certo punto premo CTRL-C e ritorno al prompt. Spero di essere stato chiaro.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 10:59   #8
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Innanzitutto, non puoi passare un _tuo_ signal handler tramite exec, in quanto il tuo spazio di indirizzi (compreso il codice dell'handler!) viene completamente riscritto dalla exec.
Puoi intercettare il segnale dal processo principale e uccidere il child con un segnale, se è ciò che intendi fare.
Quote:
ma nel momento in cui eseguo la exec di un comando, il signal handler ritorna quello di default
Solo per il child, per il motivo che ti ho esposto.
Il parent continua ad utilizzare gli handler che ha definito.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:08   #9
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Certo è proprio questo il problema, cioè che il child eseguendo la exec non ha più il signal handler del padre. E se faccio un controllo del tipo WIFSIGNALED(status) e WTERMSIG(status) al ritorno dalla wait? Potrei vedere se il figlio è stato terminato con un segnale e con quale segnale no? Però l'unica cosa è che quando so il segnale con il quale è stato terminato, se il segnale ad esempio è SIGINT, quale signal handler viene eseguito?

Grazie.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:13   #10
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Continuo a non capire...
Come può il child beccarsi un segnale in seguito a ctrl+c dalla console? E' impossibile, a meno che non hai per errore invocato la exec nel ramo del parent della fork e non nel ramo del child...
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:21   #11
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Allora facciamo così, cerco di fare un esempio. Il figlio tramite la funzione exec() esegue ls -l e riceve questo output:

file1
file2
file3
file4
file5
ecc.

Mettiamo il caso che i file all'interno della directory che sto listando sono tantissimi (sono 10000 file). Io non voglio aspettare che finisca di elencarli tutti (magari ci mette un po) quindi ad un certo punto, prima che finisce di elencare tutto il contenuto, premo CTRL-C. Una volta premuto dovrà eseguire un signal handler (che per forza di cose sarà quello di default dato che ho eseguito la exec()). Io però devo fare in modo di tornare a questa istruzione "sprintf(buf,"%s $ ", get_current_dir_name()); ed è per questo che mi serve il mio signal handler.
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:29   #12
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Se posti un pò di codice forse possiamo intenderci meglio...
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 11:35   #13
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
main.c

Codice:
#include "functions.h"

int main(void){

extern int errno;
int i;
pid_t pid;
int status;
ssize_t nread;
ssize_t nwrite;
struct sigaction sigint_handl;
char *buf=(char *)malloc(sizeof(char)*COMM_LENGTH);
char *name=(char *)malloc(sizeof(char)*COMM_LENGTH);

sigint_handl.sa_handler=sigint_handler;

if (sigemptyset(&sigint_handl.sa_mask)!=0){
   perror("sigemptyset failed"); 
   exit(SIGH_ERR); 
}

sigint_handl.sa_flags=0;

if(sigaction(SIGINT,&sigint_handl,NULL)){
   perror("sigaction failed");
   exit(SIGH_ERR);
}

while(1){
   sprintf(buf,"%s $  ", get_current_dir_name());

   if ((nwrite=write(STDOUT_FILENO,buf,COMM_LENGTH)) != COMM_LENGTH){
      perror("write error");
      if (buf!=NULL){
         free(buf);
         buf=NULL;
      }
      if (name!=NULL){
         free(name);
         name=NULL;
      }
      exit(ERR_GEN);
   } 
   if( (nread = read(STDIN_FILENO,buf,COMM_LENGTH)) <= 0){
      if(errno == EINTR)
         continue;
      else{
         if (buf!=NULL){
            free(buf);
            buf=NULL;
         }
         if (name!=NULL){
            free(name);
            name=NULL;
         }
         exit(ERR_GEN);
      }  
   }
   strcpy(name,buf);
   parse(name);
   if(command_lines(name) == OK){
      if((pid=fork()) < 0){
         perror("fork error");
         if (buf!=NULL){
            free(buf);
            buf=NULL;
         }
         if (name!=NULL){
            free(name);
            name=NULL;
         }
         exit(FORK_ERR);
      }
      if(pid == 0{
      
      if(pid > 0){
         if (waitpid(pid,&status,0) == -1){
            perror("waitpid error");
            if (buf!=NULL){
               free(buf);
               buf=NULL;
            }
            if (name!=NULL){
               free(name);
               name=NULL;
            }
         continue;
         }
         if(WIFSIGNALED(status))
            signoris=WTERMSIG(status);
      }
   }
} 
return 0;
}
functions.h
Codice:
/* Librerie */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <glob.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/wait.h>
#include <sys/types.h>

/* Definizione di costanti */
#define MAX_ARGS     256         /* Numero massimo di argomenti sulla linea di comando */
#define COMM_LENGTH  256         /* Lunghezza massima di un comando */

/* Costanti per errori */
#define OK           0           /* OK */
#define F_NOTEXEC    1           /* File non eseguibile */
#define F_NOEXIST    2           /* Accesso negato o file inesistente */
#define ERR_GEN      3           /* Errore generico */
#define READ_ERR     4           /* Read error */
#define WRITE_ERR    5           /* Write error */
#define FORK_ERR     6           /* Fork error */
#define SIGH_ERR     7           /* Errore del signal handler */

/* Variabili globali */
char *args[MAX_ARGS];            /* Argomenti sulla linea di comando */
glob_t pglob;                    /* Variabile per il trattamento del filename expansion */

/* Definizione di funzioni */
int command_lines(char *);       /* Cerca la locazione del comando e restituisce il pathname completo */
void parse(char *);              /* Analizza il comando passato suddividendo gli argomenti */
void sigint_handler(int);        /* Signal handler per CTRL-C */
void sigquit_handler(int);       /* Signal handler per CTRL-\ */
sigint_handler.c
Codice:
#include "functions.h"

void sigint_handler(int signo){
   if(signo != SIGINT){
      printf("Something wrong, handler for SIGINT");
      exit(SIGH_ERR);  
   }
   else
      return;
}
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:02   #14
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Codice:
      if(pid == 0{
      
      if(pid > 0){
!?
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 12:16   #15
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Il codice non è completo (mica ho finito tutto)

E quello è proprio il famoso ramo child che devo implementare (sempre che quella soluzione vada bene per quello che devo fare io).
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 14:30   #16
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Comunque, come per le altre funzioni, in caso di segnale intercettato la waitpid ritorna -1 con errno==EINTR. Puoi, in questo caso, inviare manualmente un SIGTERM al child; ad es. qualcosa tipo:

Codice:
  if(pid > 0){
    if (waitpid(pid, &status, 0) == -1) {
      if (errno!=EINTR)
        perror("waitpid")
      else {
        kill(pid, SIGTERM);
/* necessario per evitare uno zombie */
        do {
         if (waitpid(pid, &status, 0)!=-1)
            break; 
        } while(errno==EINTR);
      }
      continue;
    } else {
      <ramo child>
    }
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 15:04   #17
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Ok però in questo caso sono io che mando un segnale esplicitamente. Io invece devo intercettare un segnale proveniente dal figlio (nel mio caso CTRL-C). Perché, ripeto, durante la exec() nel ramo child, nell'ipotesi in cui io prema CTRL-C deve partire il signal handler creato da me. Nel tuo codice:

Codice:
if (waitpid(pid, &status, 0) == -1) {
      if (errno!=EINTR)
        perror("waitpid")
      else {
        kill(pid, SIGTERM);
attendi che arrivi un segnale ma poi non capisco perché tu debba terminare il figlio con SIGTERM. Se io interrompo il figlio con SIGINT, ad esempio, la funzione waitpid() tornerà -1 quindi che bisogno c'è di riterminare il figlio con la kill()?
Manugal è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 15:32   #18
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
Quote:
Originariamente inviato da Manugal
Ok però in questo caso sono io che mando un segnale esplicitamente. Io invece devo intercettare un segnale proveniente dal figlio (nel mio caso CTRL-C).
Non funziona così. Come può un segnale "partire dal figlio"?

Quote:
Perché, ripeto, durante la exec() nel ramo child, nell'ipotesi in cui io prema CTRL-C deve partire il signal handler creato da me.
Infatti parte, nel parent. Non nel child, per i motivi che ti ho detto.

Quote:
Se io interrompo il figlio con SIGINT, ad esempio, la funzione waitpid() tornerà -1
Se waitpid ritorna -1 vuol dire che è stata interrotta, non che il child è terminato.

Esercitati con questo programmino, modificandolo a tuo piacimento, per vedere come funziona il tutto:
Codice:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>

static void sigint_handler(int signo) {
	fprintf(stderr, "Caught signal %d\n", signo);
}

int main()
{
	struct sigaction sigint_handl;
	pid_t pid;
	
	sigint_handl.sa_handler = sigint_handler;
	sigemptyset(&sigint_handl.sa_mask);
	sigint_handl.sa_flags = 0;
	sigaction(SIGINT, &sigint_handl, NULL);

	pid = fork();
	if (pid==0) {
		char *args[] = { "sleep", "10", NULL };
		/* Senza setsid, il ctrl+c giunge anche al child. Potrebbe essere
		    desiderabile, oppure no.
		    Nota che un kill -INT <pid del parent> non giunge anche al child! */
		setsid();
		execv("/bin/sleep", args);
		perror("execv");
	} else {
		while(1) {
			int status;
			int ret = waitpid(pid, &status, 0);
			if (ret<0) {
				if (errno!=EINTR)
					perror("waitpid");
				else {
					fprintf(stderr, "Killing child...\n");
					/* Nel caso che:
					  * 1) Il segnale non sia stato inviato anche al child
					  *     (ad es. un SIGINT mandato direttamente al parent)
					  * 2) Il child gestisce e non termina su SIGINT
					  * allora accertiamoci di terminare il child manualmente.
					 */
					kill(pid, SIGTERM);
				}
			} else {
				fprintf(stderr, "Child done. status=%d\n", status);
				break;
			}
		}
	}
	return 0;
}
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 15:37   #19
ilsensine
Senior Member
 
L'Avatar di ilsensine
 
Iscritto dal: Apr 2000
Città: Roma
Messaggi: 15625
...il tutto, beninteso, se ho capito cosa ti serve: su ctrl+c, accertarti che il child ("ls" nel tuo caso) sia annullato.
__________________
0: or %edi, %ecx; adc %eax, (%edx); popf; je 0b-22; pop %ebx; fadds 0x56(%ecx); lds 0x56(%ebx), %esp; mov %al, %al
andeqs pc, r1, #147456; blpl 0xff8dd280; ldrgtb r4, [r6, #-472]; addgt r5, r8, r3, ror #12
ilsensine è offline   Rispondi citando il messaggio o parte di esso
Old 27-12-2006, 15:39   #20
Manugal
Senior Member
 
L'Avatar di Manugal
 
Iscritto dal: Jan 2001
Città: Villanova di Guidonia (RM)
Messaggi: 1079
Ok, grazie ci proverò.
Manugal è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Intervista a Stop Killing Games: distruggere videogiochi è come bruciare la musica di Mozart Intervista a Stop Killing Games: distruggere vid...
Samsung Galaxy S25 Edge: il top di gamma ultrasottile e leggerissimo. La recensione Samsung Galaxy S25 Edge: il top di gamma ultraso...
HP Elitebook Ultra G1i 14 è il notebook compatto, potente e robusto HP Elitebook Ultra G1i 14 è il notebook c...
Microsoft Surface Pro 12 è il 2 in 1 più compatto e silenzioso Microsoft Surface Pro 12 è il 2 in 1 pi&u...
Recensione REDMAGIC Astra Gaming Tablet: che spettacolo di tablet! Recensione REDMAGIC Astra Gaming Tablet: che spe...
Tesla sta per lanciare il Robotaxi nella...
Dead Island 2 arriva su Mac, ma a un pre...
FIA e Formula E rinnovano il matrimonio:...
Windows 11 24H2 approda su nuovi sistemi...
Le restrizioni americane hanno generato ...
Una Mercedes EQS con batterie allo stato...
Il robot Walker S2 della Cina cambia la ...
Cosa vuol dire "vantaggio quantisti...
Retelit punta sulla connettività ...
Novità WhatsApp: promemoria sui m...
AMD: la prossima generazione di schede v...
MediaWorld potrebbe diventare cinese: Ce...
Amazon in delirio da sconti: 22 articoli...
EOLO ha più di 700 mila utenti in...
Una spin-off del MIT ha creato dei super...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 05:24.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v