서버 프로그램 질문입니다..(RTS, Thread 관련)

yurina의 이미지

채팅서버를 만들었는데요..

리눅스 2.6.18 버젼에서

기본은 RTS를 사용했구요 멀티 스레드를 사용하여 구현했습니다.

[메인 스레드] ->>> 스레드 할당
|
[하위 스레드 ]... --->> 패킷을 받는다.
|
[데이터 처리 스레드]..... -->> 하위스레드에서 큐로 넣은 데이터를 읽어서 처리

대충 이러한 구조인데요..

이게 몇일정도 돌리다 보면 갑자기 socket이 close가 마구마구 되면서 서버는 죽지않고 클라이언트가 보낸 패킷을 받지도 못해요...

이상태로 클라이언트가 계속 끊기기만 하구 연결이 안되요..

또 서버에서 socket timeout 체크 하는데 close되지 않은 사용자들은 패킷이 오지 않으니 timeout된것으로 인식하여 결국은 socket close가 되는것 같습니다..

고치려구 로그를 봤는데...core파일이 떨어지는 것도 아니구 그부분이 에러가 나지두 않구 갑자기 막 close가 되니...원인을 몰라서..
어떻게 손을 못쓰구 있습니다...

혹 의심가는 부분이 있으면 알려주세요~

아 그리구 로그를 보니까요...같은 fd번호가 여러번 close된다구 나오는데...실제로 안끊겨서 이러는건지...잘 모르겠어요..

/*------------------------------------------------------*/
/*	Signal이 오면 Queue로 보내는 스레드		*/
/*------------------------------------------------------*/
void *recv_thread(void *rts_num)
{
	int 	signum=0, ret=0, wsize=0, time=0, count=0, num=0;
	char	buf[10000], temp[10000], fd[7];
	
	struct	FD_DATA		data;
	struct	siginfo		si;
	struct 	sockaddr_in 	cname;	
	socklen_t 	clen;
	sigset_t 	set;
	fd_sig		lfd_sig;
	
	map<int, struct FD_DATA>::iterator      i_fd;	
	multimap<int, fd_sig>::iterator 	mi; 
	
	signum = *((int *)rts_num);
	
    	gpid = getpid(); 

        sigemptyset(&set);
    	sigaddset(&set, SIGRTMIN+signum);
    	sigprocmask(SIG_BLOCK, &set, NULL);
    	    	
	usleep(100);

	pthread_cond_signal(&sync_cond);  
	
	num = sizeof(int);
    	
    	while(1)
    	{	
	        clen = sizeof(cname);
	        ret = sigwaitinfo(&set, &si);
	        
	        //_debug(_fl, "___________________Input [%d]\n", si.si_fd);
	        
	        memset(buf,0x00, sizeof(buf)); 
	        memset(temp, 0x00, sizeof(temp));
	        
	        if (ret == SIGRTMIN+signum)
	        {	    
	        	int isize, ipos, len;
	        	    
	        	while(1)
	        	{
	        		wsize = read(si.si_fd, buf, sizeof(buf));	        		
	        		if(wsize <= 0)
	        		{
	        			Lock(mutex_fd);
	        			
	        			i_fd = fd_data.find(si.si_fd);
	        			if(i_fd == fd_data.end())
	        			{
	        				unLock(mutex_fd);
	        				close(si.si_fd);	        				
	        				break;
	        			}
	        			
	        			time = GetTime();
	        			
	        			if(i_fd->second.lastsig == 0)	//socket close
	        			{
	        				_debug(_fl, "[DAT]Close FD[%d]\n", si.si_fd);
						close(si.si_fd);
												
						sprintf(buf, "%s\t%6d", CLOSE, si.si_fd);
						unLock(mutex_fd);
						
						Lock(mutex_data);		//data queue send
						in_data.push(buf);
						unLock(mutex_data);						
						pthread_cond_signal(&sync_data); 
		        					        			
				                Lock(mutex_lock);		//thread pool erase
				                			                			                
				                mi = pool_list.begin();						                
				                while(mi != pool_list.end())
				                {				                	
				                	if (mi->second.signum == signum)
				                	{				                    		
				                        	lfd_sig = mi->second;
				                        	
				                        	count = mi->first - 1;				                        	
				                        	pool_list.erase(mi);				                        	
				                        	pool_list.insert(pair<int, fd_sig>(count, lfd_sig));
				                        	
				                        	break;
				                    	}
				                    
				                	*mi++;
				                }				                
				                
				                unLock(mutex_lock);				                
	        			}
	        			else if( (time - i_fd->second.lastsig) < 3 )	//end data
	        			{
	        				i_fd->second.lastsig = 0;
	        				unLock(mutex_fd);
	        			}
	        			
	        			break;
	        		}
	        		else	//데이터 처리
	        		{
	        			Lock(mutex_fd);
	        			
	        			i_fd = fd_data.find(si.si_fd);
	        			if(i_fd == fd_data.end())		//connect
	        			{
	        				_debug(_fl, "[DAT]Connect FD[%d]\n", si.si_fd);
	        				
	        				memset(&data, 0x000, SZ_FD_DATA);
	        				data.lastsig 	= GetTime();
	        				data.lasttime	= GetTime();
	        				fd_data[si.si_fd] = data;
	        				
	        				isize = wsize;
	        				memcpy(&temp, buf, wsize);
	        			}
	        			else
	        			{		
		            			isize = wsize + i_fd->second.buflen;
		            			
		            			//_debug(_fl, "isize[%d], wsize[%d], buflen[%d]\n", isize, wsize, i_fd->second.buflen);
		            			
			            		memcpy(&temp, i_fd->second.buf, i_fd->second.buflen);
			            		memcpy(&temp[i_fd->second.buflen], buf, wsize);
				            	
				            	memset(i_fd->second.buf, 0x00, sizeof(i_fd->second.buf));
			            		i_fd->second.buflen 	= 0;
			            		i_fd->second.lastsig 	= GetTime();
			            		i_fd->second.lasttime	= GetTime();
	        			}
	        			
	        			unLock(mutex_fd);
	        			
	        			ipos = 0;
					
					while(ipos < isize - num)
					{
						memcpy(&len, &temp[ipos], num);
											
						if( (isize - num)  - ipos < len )		break;		//패킷이 전부 오지 않음	

						//_debug(_fl, "isize=[%d], ipos=[%d], len=[%d]\n", isize, ipos, len);
						
						memset(&fd, 0x00, sizeof(fd));
						sprintf(fd, "%6d", si.si_fd);
						memcpy(temp+8, fd, 6);				//fd value copy
																		
			            		Lock(mutex_data);
						in_data.push(temp+5);
						unLock(mutex_data);
						
						pthread_cond_signal(&sync_data); 
						
						ipos += len + num;	
					}	//end while()
														
					Lock(mutex_fd);
		        			
			            	i_fd = fd_data.find(si.si_fd);
			            	if(i_fd == fd_data.end())
			            	{
			            		_debug(_fl, "[ERR]FD정보를 찾을수 없습니다.\n");
			            	}
			            	{
			            		if(isize == ipos)	memset(&temp, 0x00, sizeof(temp));
			            		
						i_fd->second.buflen = isize - ipos;
																		
						if(i_fd->second.buflen > 0)
						{
							_debug(_fl, "[DAT]패킷이 전부 오지 않았다.buflen[%d]\n", i_fd->second.buflen);
							memcpy(i_fd->second.buf, temp + ipos, i_fd->second.buflen);
						}
					}
					
					unLock(mutex_fd);     
	        		}
	        		
	        	}	//end while()	
	        }	//end if()
    	}
    	
    	pthread_detach(pthread_self());
    	pthread_exit(0);
	return NULL;
}

이게 문제의 패킷을 받아서 넘기는 부분 소스인데요 저기 close하는 부분은 클라이언트로 부터 signal이 와야만 수행할수 있는 부분인데...서버의 버그로 갑자기 계속 signal이 발생하면서 close가 될수 있나요?

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.