线程干扰代理中的malloc?

时间:2012-03-04 07:03:34

标签: concurrency proxy thread-safety malloc semaphore

我正在尝试将顺序代理转换为并发代理,其中多个线程可以处理来自Web浏览器(如Firefox)的多个请求。现在我被困在尝试使用信号量来使我的代理线程安全。我已经通过用gethostbyname_r替换它来处理gethostby名称不是线程安全的情况。问题可能出在我的mallocing中,因为我还不熟悉这个概念。当我编译时,我得到一个无效点或免费或一个人。我不知道我是否需要malloc我在PARSE URI部分

中已经做过的变量
#include "csapp.h"
#include <pthread.h>
#include <semaphore.h>

/* Globals */ 
FILE *log_file; /* Log file with one line per HTTP request */
sem_t mutex,maa, muu, mqq,mpp, mkk,mll;

typedef struct {
int clientfdpNum;
struct sockaddr_in *sockaddrT;
} thread_args;
 /* processRequest */
void processRequest(int proxyfd, struct sockaddr_in *sockaddr) {
P(&maa);
char fline[MAXLINE];
char rest[MAXLINE];
char method[MAXLINE], version[MAXLINE], uri[MAXLINE];
//P(&muu);
readLine(proxyfd, fline, MAXLINE); //reads firstline
read(proxyfd,rest, sizeof(rest)); //reads rest of request

//Read request line and headers 
sscanf(fline, "%s %s %s", method, uri, version);
//V(&muu);
//printf("\n%s\n",method);
//printf("URI %s\n",uri);
// printf("%s\n",version);
if (strcasecmp(method, "GET")) { 
clienterror(proxyfd, method, "501", "Not Implemented",
            "Proxy does not implement this method");
return;
}

//********************************Parse URI***********************************//

char *ip;
ip = (char*) Malloc(MAXLINE);
int newPort =80;
char *page;
page =  (char*) Malloc(MAXLINE);
char* slash;
slash = (char*) Malloc(MAXLINE);


sscanf(uri, "http://%99s[^:]:%99d/%99s[^\n]", ip, &newPort, page);
//printf("IP: %s\n",ip);
//printf("port: %d\n", newPort);
printf("page: %s\n", page);
page = strchr(ip,'/');
strcpy(slash,page);

char* colon = strchr(ip,':'); //find where colon is if port specified
if(colon != NULL){ //colon with new port is in ip
  colon++; //skip over colon
  newPort = atoi(colon); //convert to integer
  //printf("colon part: %s \n",colon);  
  colon--;
  *colon = '\0'; //terminate it earlier
} else{
int size = strlen(ip);
int size2 = strlen(page);
ip[size-size2]='\0';
}
V(&maa);
P(&mqq);
printf("\nnew IP: %s\n",ip);
printf("new port: %d\n", newPort);
printf("new page: %s\n", slash);



//*****************************Proxy acting as client***************************//
int clientfd;
struct hostent *hp;
struct sockaddr_in clientaddr;

if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  return;
/*
// Fill in the server's IP address and port 
if ((hp = gethostbyname(ip)) == NULL){
  printf("Gethostbyname Problem\n");
  return; 
}
*/


 struct hostent hostbuf;
 size_t buflen;
char *bufh;
int res;
int herr;
buflen = 1024;
/* Allocate buffer, remember to free it to avoid memory leakage.  */
bufh = malloc (buflen);
while( (res = gethostbyname_r( ip, &hostbuf, bufh, buflen, &hp, &herr)) == ERANGE){
/* Enlarge the buffer.  */
buflen *= 2;
bufh = realloc(bufh, buflen);
if(bufh == NULL)
  perror("realloc");
}
/*  Check for errors.  */
if (res != 0 || hp == NULL){
  printf("threadsafe null\n");
  return;
}
free(bufh);



bzero((char *) &clientaddr, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr_list[0], 
(char *)&clientaddr.sin_addr.s_addr, hp->h_length);
clientaddr.sin_port = htons(newPort);

// Establish a connection with the server
if (connect(clientfd, (SA *) &clientaddr, sizeof(clientaddr)) < 0)
return;
V(&mqq);
P(&mpp);
//*********************PRoxy acting as server back to browser****************//
char theRequest[MAXLINE] = {0};
sprintf(theRequest, "%s %s %s\r\n%s",method, slash, version, rest);
rio_writen(clientfd,theRequest,strlen(theRequest));

char buf[MAXLINE]={0};
int st,b;
int responseSize = 0;

do{
st = read( clientfd, buf, sizeof(buf) );
    //printf("%s", buf);
b = writenq(proxyfd, buf, st);
responseSize += b;
}while(st > 0);

//while(( r = recv(clientfd, buf, 1, 0))>0){
////rio_writen( proxyfd, webPAGE_buf, strlen(webPAGE_buf));
//printf("%s", buf);
//st = send( proxyfd, buf, strlen(buf), 0);
//}
close(clientfd);

//printf("Write Log\n");
//******************************WRITE LOG ***********************************//
char logstring[256];
//formats data aquired.
format_log_entry(logstring, sockaddr, ip, responseSize);
//writes to log
V(&mpp);

P(&mutex);  //Lock

fputs(logstring, log_file);
fflush(log_file);
free(ip);
free(slash);
free(page);

close(proxyfd);

V(&mutex); //Unlock
}

/* Thread routine */
void *thread(void *vargp){
  P(&mkk);
Pthread_detach(pthread_self());
thread_args *my_args = (thread_args *)vargp;
int clientfdp = my_args->clientfdpNum;
struct sockaddr_in *sockaddr = my_args->sockaddrT;

free(vargp);
V(&mkk);
//printf("process request in thread %d\n", clientfdp);
processRequest(clientfdp, sockaddr);

 return NULL;
}

/* main - Main routine for the proxy program*
int main(int argc, char **argv)
{
int sockfd, clientfdp, port;
struct sockaddr_in Clientaddr;
socklen_t clientlen = sizeof(Clientaddr);
pthread_t tid;
sem_init(&mutex, 0, 1);
sem_init(&muu, 0, 1);
sem_init(&maa, 0, 1);
sem_init(&mqq, 0, 1);
sem_init(&mpp, 0, 1);
sem_init(&mkk, 0, 1);
sem_init(&mll, 0, 1);

/* Check arguments */
if (argc != 2) {
  fprintf(stderr, "Usage: %s <port number>\n", argv[0]);
  exit(0);
}
signal(SIGPIPE, SIG_IGN);
//convert second Argument to integer
port = atoi(argv[1]);

//open log file
log_file = Fopen("Proxy.log","a");
if( log_file == NULL ){
puts ( "Cannot open Log file\n" );
exit(1);
 }

sockfd = open_listenfd(port);
//takes care of Socket, Bind, and Listen

while(1){
if((clientfdp = Accept(sockfd, (SA *)&Clientaddr, &clientlen)) < 0)
  err_exit();

thread_args *arguments = malloc(sizeof(thread_args));
arguments->clientfdpNum = clientfdp;
arguments->sockaddrT = &Clientaddr;
Pthread_create(&tid, NULL, thread, arguments);

//processRequest(clientfd, &Clientaddr); >> in thread
//close client fill descriptor
//close(clientfd);  >>in thread
}
exit(0);
}


void format_log_entry(char *logstring, struct sockaddr_in *sockaddr, char *uri, int size) {
time_t now;
char time_str[MAXLINE];
unsigned long host;
unsigned char a, b, c, d;

/* Get a formatted time string */
now = time(NULL);
strftime(time_str, MAXLINE, "%a %d %b %Y %H:%M:%S %Z", localtime(&now));
host = ntohl(sockaddr->sin_addr.s_addr);
a = host >> 24;
b = (host >> 16) & 0xff;
c = (host >> 8) & 0xff;
d = host & 0xff;
/* Return the formatted log entry string */
sprintf(logstring, "%s: %d.%d.%d.%d %s %d\n", time_str, a, b, c, d, uri, size);
}

char* readLine(int clientfd, char* line, int maxlen) {
// read one character at a time until we encounter \n
char c='a';
char* lineptr=line;
int nread=0;     
do {  
if(read(clientfd, &c, sizeof(c)) < 0) {
  if(errno==EINTR)
continue;
  err_exit();
}
nread++;
*lineptr++=c;    
} while(c != '\n' && nread<maxlen-1);

if(c=='\n')
  *(lineptr-1)=0; // overwrite \n if present
else
  *lineptr=0; // do not overwrite if different character
return line;
}

 /* writenq - writes and also handles SIGIN the signal interupt.  */
 size_t writenq(int fd, void *vptr, size_t n){
 size_t nleft;
size_t nwrite;
char *ptr;
ptr = vptr;
nleft = n;

while(nleft >0){
if((nwrite= write(fd, ptr, n)) <0){
  if(errno == EINTR)
nwrite=0;
  else 
return -1;
}
else if(nwrite ==0)
  break;

nleft -=nwrite;
ptr += nwrite;
}
return (n-nleft);
}

1 个答案:

答案 0 :(得分:0)

不要使用线程,使用异步IO来避免这些问题。