void TCPServer::stop() { //1.停止工作线程 if (m_nServerThreadId != 0) exitThread(&m_nServerThreadId, &m_bThreadRunFlag); m_bThreadRunFlag = false; //2.关闭监听 m_objListenTCPTransfer->close(); delete m_objListenTCPTransfer; m_objListenTCPTransfer = NULL; //3.销毁epoll文件描述符 ::CLOSESOCKET(m_nEpollFd); //4.清理连接对象列表 std::list<TCPLinkReceiver*>::iterator it = m_objTCPLinkReceiverList.begin(); for (; it != m_objTCPLinkReceiverList.end(); ++it) { TCPLinkReceiver* pobjTCPLinkReceiver = *it; if (NULL != pobjTCPLinkReceiver) delete pobjTCPLinkReceiver; } m_objTCPLinkReceiverList.clear(); }
void OperationQueue::Impl::workerThread() { for (;;) { Record::Ptr item; { LockGuard lock(_inputMutex); item = getFirstUndoInputRecord(); if (!item) { exitThread(ThreadInfo::thisThreadId()); return; } item->state = Record::State::Doing; if (item->isCancel) { popupInputRecord(item->Id); continue; } } item->operation->action(); { LockGuard lock(_inputMutex); if (!item->isCancel && item->callback != nullptr) { s_addItem(_outputs, item, _outputMutex); } popupInputRecord(item->Id); } } }
int xWorkingThread::stop() { if(m_pRunner == NULL) return 1; exitThread(true); return 0; }
void Main () { int i, me; void printMyThread(); initThreads (); me = getThread (); for(i=1; i<MAXTHREADS; i++) spawnThread(printMyThread,0); for (i = 0; i < NUMYIELDS; i++) { Printf("0 T%d\n",me); yieldThread(1); } exitThread (); }
void DemuxThread::stopPlay() { fprintf("stop demux thread\n"); if(m_videoDecoder != NULL) { m_videoDecoder->exitThread(); bool ret = m_videoDecoder->wait(); if(!ret) { fprintf(stderr, "force to stop video thread\n"); m_videoDecoder->setThreadStatus(THREAD_STOP); m_videoDecoder->quit(); } } exitThread(); bool ret = wait(); if(!ret) { fprintf("force to stop video thread\n"); quit(); } releaseVideoInfo(); }
/* Thread per sessione di connessione */ static void *Session (void *p) { int clifd; /* Socket Client-Proxy */ int servfd; /* Socket Proxy-Server */ int ris; /* Utili */ struct Request req; /* Conterrà le informazioni per forward e prefetch */ struct Response resp; /* Conterrà info per invio file cache, struttura richiesta da prepareResponse ecc */ char cache_filename[MAXLENPATH]; char error_response[16]; char buffer[MAXLENRESP]; int buffer_len; struct sockaddr_in Local, Serv; /* Per connessione con il server */ /* Client socket Timeout */ struct timeval timercli; timercli.tv_sec = INACTIVITY_TIMEOUT_SECONDS; timercli.tv_usec = 0; /* Estrazione informazioni parametro thread */ clifd = ((struct param*)p)->fd; free(p); p = NULL; /* Controllo sul numero dei thread */ pthread_mutex_lock(&mutex_num); if(numthread < MAXNUMTHREADWORKING) numthread++; pthread_mutex_unlock(&mutex_num); if(numthread >= MAXNUMTHREADWORKING) { close(clifd); exitThread(); return(NULL); } #ifdef DEBUG printf("Thread: %ld. Client FD passato: %d\n", pthread_self(), clifd); fflush(stdout); #endif /* Imposto il timeout per questo socket client */ setsockopt(clifd, SOL_SOCKET, SO_RCVTIMEO, &timercli, sizeof(struct timeval)); setsockopt(clifd, SOL_SOCKET, SO_SNDTIMEO, &timercli, sizeof(struct timeval)); /* Inizializzo struttura per richiesta */ initRequest(&req); /* Prelevo la richiesta ed estraggo le informazioni. Se a buon fine l'avrò tutta in req->buf, mentre il resto sarà estratto e messo negli altri campi di req. */ ris = getRequest(clifd,&req); switch(ris) { case -3: /* Client ha chiuso la connessione */ #ifdef DEBUG printf("Thread: %ld. Client ha chiuso connessione. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case -2: /* Errore in lettura, chiudo thread e connessione */ #ifdef DEBUG printf("Thread: %ld. Errore in lettura client request. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case -1: /* Lettura richiesta terminata, formato richiesta sbagliato */ strcpy(error_response, "403\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Lettura req terminata, formato richiesta sbagliato. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case 1: /* Lettura richiesta OK -> proseguo */ #ifdef DEBUG printf("Thread: %ld. Lettura req OK. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif break; default: /* Errore sconosciuto */ strcpy(error_response, "402\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Errore sconosciuto. \nBuffer: %s\n", pthread_self(), req.buf); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; } /* Switch */ /* Ora ho nella struttura Request tutte le informazioni che mi servono */ /* Tentativi connessione server */ int servconn_chance = SERVER_CHANCE; /* Ogni qualvolta ritento una connessione con il server per errori, ricontrollo di avere il file in cache, qualche altro thread potrebbe averlo salvato nel frattempo. */ while (1) { #ifdef DEBUG printf("Controllo su thread: %ld. While session().\n", pthread_self()); fflush(stdout); #endif /* Se ha fatto una richiesta GET e ho il file in cache */ if ((req.reqType == GET) && (get_cache_name(&(req.inaddr), req.port, req.path, cache_filename))) { /* Cerco di preparare la risposta da mandare (Anche con RANGE), l'eventuale contenuto del file è nel buffer di resp */ ris = prepareGetResponse(&req, &resp, cache_filename); #ifdef DEBUG printf("Thread: %ld. La req è GET e ho il file in cache. \nFile: %s\n", pthread_self(), resp.buf); fflush(stdout); #endif switch(ris) { case 1: ris = mysend(clifd, resp.buf, resp.lenresp); /* caso OK ------> MANDO AL CLIENT IL FILE CHE ERA IN CACHE e chiudo */ if (ris == -1) { printf ("Error on cached file response send.\n"); fflush(stdout); } if (ris == -2) { printf ("Time out on cached file response send.\n"); fflush(stdout); } if (ris == 0) { printf ("Client closed connection before sending cached file.\n"); fflush(stdout); } else { printf ("Cached file sent to client.\n"); fflush(stdout); } close(clifd); exitThread(); return(NULL); break; case -3: /* file not found (expired nel frattempo) ---> faccio la richiesta */ #ifdef DEBUG printf("Thread: %ld. Avevo il file ma è expired. \n", pthread_self()); fflush(stdout); #endif break; case -4: /* interval not found -----> lo notifico */ strcpy(error_response, "405\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Avevo il file ma il RANGE è sbagliato. \n", pthread_self()); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; case -5: /* unknown error */ default: strcpy(error_response, "402\n\n"); mysend(clifd, error_response, strlen(error_response)); #ifdef DEBUG printf("Thread: %ld. Avevo il file ma dopo la prepareResponse errore sconosciuto.\n", pthread_self()); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); break; } } /* Fine GET e ho il file in cache */ /* Non ho file in cache oppure richiesta INF -> Forward richiesta al server e poi discrimino in base a GET (prefetch) e INF (solo forward risposta) */ servfd = socket(AF_INET, SOCK_STREAM, 0); if (servfd < 0) { printf("Thread: %ld. Chiamata a socket() per serverfd fallita. Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); close(clifd); exitThread(); return(NULL); } /* Server socket Timeout */ struct timeval timerserv; timerserv.tv_sec = INACTIVITY_TIMEOUT_SECONDS; timerserv.tv_usec = 0; if ((SetsockoptReuseAddr(servfd) == 0) || (setsockopt(servfd, SOL_SOCKET, SO_RCVTIMEO, &timerserv, sizeof(struct timeval)) != 0) || (setsockopt(servfd, SOL_SOCKET, SO_SNDTIMEO, &timerserv, sizeof(struct timeval)) != 0)) { printf("Thread: %ld. Error on a setsockopt for server socket\n", pthread_self()); fflush(stdout); close(servfd); close(clifd); exitThread(); return(NULL); } /* Binding */ memset(&Local, 0, sizeof(Local)); Local.sin_family = AF_INET; Local.sin_addr.s_addr = INADDR_ANY; Local.sin_port = htons(0); ris = bind(servfd, (struct sockaddr *)&Local, sizeof(Local)); if (ris < 0) { printf("Thread: %ld. Chiamata a bind() per serverfd fallita. Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); close(servfd); exitThread(); return(NULL); } /* Compilo campi server */ memset(&Serv, 0, sizeof(Serv)); Serv.sin_family = AF_INET; Serv.sin_addr.s_addr = req.inaddr.s_addr; Serv.sin_port = htons(req.port); #ifdef DEBUG printf ("Thread: %ld, %d° tentativo connessione con server. FD: %d\n", pthread_self(), (SERVER_CHANCE-servconn_chance+1), servfd); fflush(stdout); #endif int repeat; repeat = 0; while (1) { #ifdef DEBUG printf("Controllo su thread: %ld. While connect session.\n", pthread_self()); fflush(stdout); #endif ris = connect (servfd, (struct sockaddr *)&Serv, sizeof(Serv)); if (ris < 0) { if ((errno == EINTR) || (errno == EINPROGRESS)) ; /* Ritento */ if (errno == EISCONN) { printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno)); fflush(stdout); repeat = 0; break; } else { printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno)); fflush(stdout); if (servconn_chance > 0) servconn_chance--; /* Ritento */ else { printf("Thread: %ld, Chiamata a connect() per serverfd fallita. FD: %d. Errore: %d \"%s\"\n", pthread_self(), servfd, errno,strerror(errno)); fflush(stdout); close(servfd); exitThread(); return(NULL); } /* Ritento nuovo socket */ repeat = 1; break; } /* Errore non recuperabile */ } /* Error on connect */ else { /* OK */ repeat = 0; break; } } /* Connect while */ /* Se è il caso torno indietro */ if (repeat) continue; /* Forwardo la richiesta, qualunque essa sia (inf/get) */ #ifdef DEBUG printf("Thread: %ld. Forward richiesta del client al server.\n Req: %s\n", pthread_self(), req.buf); fflush(stdout); #endif ris = mysend(servfd, req.buf, strlen(req.buf)); if (ris < 0) { #ifdef DEBUG printf("Thread: %ld. Errore su forward req.\n", pthread_self()); fflush(stdout); #endif if (servconn_chance > 0) { servconn_chance--; close(servfd); continue; /* Chiudo questa connessione e ritento */ } else { close(clifd); close(servfd); exitThread(); return(NULL); } } /* Aspetto la risposta del server */ ris = myread(servfd, buffer, MAXLENRESP); if (ris <= 0) { #ifdef DEBUG printf("Thread: %ld. Errore in risposta server a forward req del client.\nErrore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); #endif if (servconn_chance > 0) { servconn_chance--; close(servfd); continue; /* Chiudo questa connessione e ritento */ } else { close(clifd); close(servfd); exitThread(); return(NULL); } } #ifdef DEBUG printf("Thread: %ld. OK arrivo risposta dal server per forward al client.\n Resp: %s\n", pthread_self(), buffer); fflush(stdout); #endif /* Concludo chiusura con server */ close(servfd); /* Terminatore */ buffer[ris] = '\0'; buffer_len = ris; /* Controllo errori 40X nel qual caso forwardo e chiudo */ if ((!(strncmp(buffer,"402\n\n",5))) || (!(strncmp(buffer,"403\n\n",5))) || (!(strncmp(buffer,"404\n\n",5))) || (!(strncmp(buffer,"405\n\n",5)))) { #ifdef DEBUG printf("Thread: %ld. Server ha inviato un errore 40X, faccio forward al Client", pthread_self()); fflush(stdout); #endif ris = mysend(clifd, buffer, buffer_len); close(clifd); exitThread(); return(NULL); } /* Se la richiesta era INF faccio un parsing per INF e invio a client */ if (req.reqType == INF) { /* Corretto */ if (parseINF(buffer, buffer_len) == 0){ ris = mysend(clifd, buffer, buffer_len); if (ris < 0) /* Errore irreparabile col client */ #ifdef DEBUG printf("Thread: %ld. Errore in risposta a Client (dopo arrivo dal server).\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); } /* Errato */ else continue; /* Ritento */ } /* Se la richiesta era GET per RANGE faccio il parsing per RANGE e poi invio il file */ if (req.is_range) { /* Corretto */ if (parseRANGE(buffer, buffer_len) == 0) ; /* Vado comunque a fare il parsing per fare prefetch sugli URL che trovo */ /* Errato */ else continue; /* Ritento */ } int expire; char cachename[MAXLENPATH]; struct timeval tod; /* Se invece la richiesta era GET per file completo prima faccio parsing per GET completo. Se corretto salvo il file (così è a disposizione di altri thread) e poi invio a client */ if (!(req.is_range)) { #ifdef DEBUG printf("Thread: %ld. Prelevo nome per caching.\n", pthread_self()); fflush(stdout); #endif /* Prelevo nome univoco */ my_tempname(cachename); #ifdef DEBUG printf("Thread: %ld. Salvo file caching.\n", pthread_self()); fflush(stdout); #endif /* SE CORRETTO E COMPLETO salvo file appena scaricato in cache e prelevo expire */ expire = buffer_data_to_file (cachename, buffer, buffer_len); /* Non completo / Corrotto */ if (expire < 0) { #ifdef DEBUG printf("Thread: %ld. Il file arrivato è corrotto.\nEcco il file:\n", pthread_self()); fflush(stdout); #endif write(1, buffer, MAXLENRESP); fflush(stdout); continue; /* Ritento da capo connessione con server e richiesta */ } else { /* Prendo tempo attuale da sommare al tempo di expire del file appena ricevuto */ gettimeofday(&tod, NULL); /* Gestione cache, aggiunta file */ add_file_cache(&(req.inaddr), req.port, req.path, (tod.tv_sec + expire), cachename); } } /* Ora ho nel buffer ciò che devo inviare a Client e in ogni caso faccio lo stesso tipo di invio */ ris = mysend(clifd, buffer, buffer_len); if (ris < 0) { /* Errore irreparabile col client */ #ifdef DEBUG printf("Thread: %ld. Errore in risposta a Client (dopo arrivo dal server).\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); #endif close(clifd); exitThread(); return(NULL); } #ifdef DEBUG printf("Thread: %ld. OK risposta dopo arrivo file del Server verso Client.\n Resp: %s\n", pthread_self(), buffer); fflush(stdout); #endif /* In ogni caso ho finito col client */ close(clifd); /* Inizializzo qui, ma viene modificato nel parsing per scorrere il buffer con la risposta */ int lenparsed = 0; struct Request *p_prefetch_req; char tmpname[MAXLENPATH]; #ifdef DEBUG printf("Thread: %ld. Fase prefetching.\n", pthread_self()); fflush(stdout); #endif while(1) { #ifdef DEBUG printf("Controllo su thread: %ld. While parse session().\n", pthread_self()); fflush(stdout); #endif /* Struttura Request per fare richiesta al server, già passabile come parametro a thread */ p_prefetch_req = (struct Request *) malloc (sizeof(struct Request)); if (p_prefetch_req == NULL){ #ifdef DEBUG printf("Thread: %ld. Errore in allocazione p_prefetch_req.\n", pthread_self()); fflush(stdout); #endif exitThread(); return(NULL); } /* Chiamo il parsing saltando almeno il minimo numero di byte che possono esserci prima dei dati. NB: USO CAMPO "buf[]" della struttura Request per l'URL!! NB2: Chiedo sia REF che IDX;REF per 1° e 2° livello */ #ifdef DEBUG printf("Thread: %ld. Fase parsing del buffer.\n", pthread_self()); fflush(stdout); #endif ris = parse((buffer+MIN_BYTE_BEFORE_DATA), &lenparsed, (buffer_len-MIN_BYTE_BEFORE_DATA), p_prefetch_req, FIRST_SECOND_LEVEL_PREFETCHING); /* Parsing finito, per errori o fine buffer */ if(ris <= 0) { exitThread(); return(NULL); } else if(ris == 1) { #ifdef DEBUG printf("Thread: %ld. OK parsing, URL estratto: %s.\n", pthread_self(), p_prefetch_req->buf); fflush(stdout); #endif /* Thread che fanno prefetch su REF - IDX+REF */ pthread_attr_t attr; pthread_attr_init(&attr); pthread_t threadID; pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); /* Se ho già il file passo al prossimo URL */ if(get_cache_name(&(p_prefetch_req->inaddr), p_prefetch_req->port, p_prefetch_req->path, tmpname)) { free(p_prefetch_req); p_prefetch_req = NULL; continue; } /* Altrimenti setto il campo reqType della struttura Request che uso come parametro al thread, impostandolo per il prefetching di primo e secondo livello.. */ p_prefetch_req->reqType = FIRST_SECOND_LEVEL_PREFETCHING; /* .. e faccio partire il thread relativo alla sessione di prefetching per URL specificato in p_prefetch_req->buf[] */ ris = pthread_create(&threadID, &attr, get_and_cache, (void *)p_prefetch_req); if(ris != 0) { printf("Thread: %ld. Chiamata a pthread_create() fallita.\n Errore: %d \"%s\"\n", pthread_self(), errno,strerror(errno)); fflush(stdout); continue; } } } /* while del parsing */ } /* While socket/binding */ } /* Session ****************/
void * ComThread::Entry(void) { struct pollfd fds[2]; ComTask *current = NULL; Notification *notify; ConnectResult connectResult; connectResult = connect(); switch (connectResult) { case Success: break; case Failure: sendComEvent(JobCtrl::ERR_CONNECT); return (0); case VersionMismatch: sendComEvent(JobCtrl::ERR_VERSION_PROT); return (0); case AuthNoKey: sendComEvent(JobCtrl::ERR_NO_KEY); return (0); case AuthWrongKeyId: sendComEvent(JobCtrl::ERR_KEYID); return (0); case AuthInvalidKey: sendComEvent(JobCtrl::ERR_INV_KEY); return (0); case AuthInvalidCert: sendComEvent(JobCtrl::ERR_INV_CERT); return (0); case AuthSysFail: sendComEvent(JobCtrl::ERR_AUTH_SYS_FAIL); return(0); } fds[0].fd = comPipe_[0]; fds[0].events = POLLIN; fds[1].fd = channel_->fd; fds[1].events = POLLIN; while (1) { /* * Step 1: Clear the notification pipe. We do this first * to ensure that other events that come in along * the way will cause the poll below to return * immediately. */ while(1) { int ret; char buf[100]; ret = read(comPipe_[0], buf, sizeof(buf)); if (ret <= 0) break; } /* Step 2: Send any pending escalation answers. */ while((notify = answerQueue_->pop()) != 0) { anoubis_token_t token; bool allowed; EscalationNotify *escalation; escalation = dynamic_cast<EscalationNotify *>(notify); if (escalation) { allowed = escalation->getAnswer()->wasAllowed(); token = escalation->getToken(); anoubis_client_notifyreply(client_, token, allowed ? 0 : EPERM, 0); } if (notify->needFree()) delete notify; } /* Step 3: If no task is running, try to start a new one. */ if (current == NULL) { Task *task = getNextTask(Task::TYPE_COM); current = dynamic_cast<ComTask *>(task); if (current && !current->shallAbort()) { current->setClient(client_); current->exec(); } } /* * Step 4: If the current task is done, handle this. * This also handles errors in current->exec() * and performs the next stpes of the task if the * task is not yet done. */ if (current && (current->shallAbort() || current->done())) { TaskEvent event(current, wxID_ANY); /* Task is no longer a COM task. Reschedule. */ if (current->getType() != Task::TYPE_COM) { JobCtrl::instance()->addTask(current); current = NULL; continue; } if (current->shallAbort()) current->setTaskResultAbort(); sendEvent(event); /* Restart in case there are more tasks on the list. */ current = NULL; continue; } /* * Step 5: At this point we have an active task that is * waiting for data from the network and all * pending answer requests have been handled. * We poll until either new Jobs or answers * become ready or a message from the daemon arrives. */ if (!isConnected() || exitThread()) break; fds[0].revents = 0; fds[1].revents = 0; if (poll(fds, 2, 60000) <= 0) { continue; } /* * Step 6: Process a message from the Daemon if there is * one. Then start over. */ if (fds[1].revents) { if (!readMessage()) break; } } /* Thread is short before exit, disconnect again */ disconnect(); return (0); }