高手请进 linux下信号量同步多线程问题
我在编写一个正则表达式匹配多线程库
使用信息量来同步工作线程(匹配线程)并等待处理结果,该程序在测试环境下没有问题,但在我的主程序中出现了问题。
我使用两个信号灯的信号量集,一个用于表示当前可用任务数(为实开工作线程数),一个用于表示当前已经完成的任务数。
程序流量如下:
《主线程》
建立任务数据缓冲区,给所有线程返回
设置已经完成任务信号灯为0,可用任务数信号灯为工作线程数
主线程完成自己的一份,并等待其它工作线程返回
完成任务,并释放缓冲(该处出现读已经FREE的数据)
《工作线程》
等待任务信号量,并取得一个信号资源
工作……
释放任务完成信号量
问题:
该库在测试环境下工作良好,主线程,即为工作(main)主线程。
工作环境,在DLL中,由辅助线程调用,出现段错误问题
使用valgrind检查发现测试环境没有问题,工作环境出现访问free数据。
以下为工作环境调试信息
[DEBUG] 2011-09-24 10:16:08.533 pcre matcher finished work, 244980032 subject:bfd4288, len:172
[DEBUG] 2011-09-24 10:16:08.548 all matcher has finished work.
[DEBUG] 2011-09-24 10:16:08.552 pcre matcher finish release signal...(244980032)
[DEBUG] 2011-09-24 10:16:08.553 pcre matcher wait to work...(244980032)
-----[DEBUG] 2011-09-24 10:16:08.595 pcre matcher finished work, 244980032 subject:bfd4288, len:172
-----[DEBUG] 2011-09-24 10:16:08.596 pcre matcher finish release signal...(244980032)
[DEBUG] 2011-09-24 10:16:08.600 pcre matcher wait to work...(244980032)
红色部分为工作线程多次访问,第二次访问的时候,资源已经释放……就出现问题了
- C/C++ code
/** * match a subject using PCRE * return 0 - success, -1 -- failed */int pcre_match(pcre_obj_t* _this, char* subject, unsigned int subject_len, void** pptag){ int result; if (_this->threads_count > 1){ pthread_rwlock_rdlock(&_this->rwlock); } *pptag = NULL; /*build subject buff include end 0*/ char* sharesubject; sharesubject = (char*)malloc(subject_len + 2); if (sharesubject == NULL) goto clean; memcpy(sharesubject, subject, subject_len); sharesubject[subject_len] = '\0'; sharesubject[subject_len+1] = '\0'; /*do match using matcher*/ if (_this->threads_count > 1){ /*enable all thread to work*/ int threadcnt = set_running_thread_match_param(_this->matcher_list, sharesubject, subject_len, pptag); threadcnt--; /* reduce main thread's share */ msg_log_debug("let all matcher to work for master, subject address:%x, len%d.", sharesubject, subject_len); do{ result = semset_set(_this->semid, TASK_FINISH_SEM_IDX, 0); }while(result == -1 && (errno == EAGAIN || errno == EINTR)); if (result == -1 && !(errno == EAGAIN || errno == EINTR)){ msg_log_warn("Unexpected error on set signal[%d].", errno); } do{ result = semset_set(_this->semid, TASK_START_SEMIDX, threadcnt); }while(result == -1 && (errno == EAGAIN || errno == EINTR)); if (result == -1 && !(errno == EAGAIN || errno == EINTR)){ msg_log_warn("Unexpected error on set signal[%d].", errno); } /* do main thread's share */ _this->matcher_list->match_result = pcre_match_item( _this->matcher_list->pattern_list, _this->matcher_list->subject, _this->matcher_list->subject_len, _this->matcher_list->pptag); /* wait all threads to finish their share */ msg_log_debug("wait all work matcher threads finish single..."); do{ semset_wait(_this->semid, TASK_FINISH_SEM_IDX, 1, threadcnt); }while(result == -1 && (errno == EAGAIN || errno == EINTR)); if (result == -1 && !(errno == EAGAIN || errno == EINTR)){ msg_log_warn("Unexpected error on set signal[%d].", errno); } msg_log_debug("all matcher has finished work."); result = get_match_result(_this->matcher_list, pptag); }else{ result = pcre_match_item(_this->matcher_list->pattern_list, sharesubject, subject_len, pptag); }clean: if (_this->threads_count > 1){ pthread_rwlock_unlock(&_this->rwlock); } if (sharesubject != NULL) free(sharesubject); return result;}
请求各位给个思路,项目很紧,先行谢过!
[解决办法]
帮顶个
[解决办法]
仅供参考
- C/C++ code
#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef WIN32 #include <windows.h> #include <io.h>#else #include <unistd.h> #include <sys/time.h> #include <pthread.h> #define CRITICAL_SECTION pthread_mutex_t #define _vsnprintf vsnprintf#endif//Log{#define MAXLOGSIZE 100000000#define ARRSIZE(x) (sizeof(x)/sizeof(x[0]))#include <time.h>#include <stdarg.h>char logfilename1[]="MyLog1.log";char logfilename2[]="MyLog2.log";char logstr[16000];char datestr[16];char timestr[16];char ms10[3];CRITICAL_SECTION cs_log;FILE *flog;int centisec() {#ifdef WIN32 return ((GetTickCount()%1000L)/10)%100;#else struct timeval tv; if (!gettimeofday(&tv,NULL)) { return ((tv.tv_usec%1000000L)/10000)%100; } else { return 0; }#endif}#ifdef WIN32void Lock(CRITICAL_SECTION *l) { EnterCriticalSection(l);}void Unlock(CRITICAL_SECTION *l) { LeaveCriticalSection(l);}#elsevoid Lock(CRITICAL_SECTION *l) { pthread_mutex_lock(l);}void Unlock(CRITICAL_SECTION *l) { pthread_mutex_unlock(l);}#endifvoid LogV(const char *pszFmt,va_list argp) { struct tm *now; time_t aclock; if (NULL==pszFmt||0==pszFmt[0]) return; if (-1==_vsnprintf(logstr,ARRSIZE(logstr),pszFmt,argp)) logstr[ARRSIZE(logstr)-1]=0; time(&aclock); now=localtime(&aclock); sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday); sprintf(timestr,"%02d:%02d:%02d",now->tm_hour ,now->tm_min ,now->tm_sec ); sprintf(ms10,"%02d",centisec()); printf("%s %s.%s %s",datestr,timestr,ms10,logstr); flog=fopen(logfilename1,"a"); if (NULL!=flog) { fprintf(flog,"%s %s.%s %s",datestr,timestr,ms10,logstr); if (ftell(flog)>MAXLOGSIZE) { fclose(flog); if (rename(logfilename1,logfilename2)) { remove(logfilename2); rename(logfilename1,logfilename2); } flog=fopen(logfilename1,"a"); if (NULL==flog) return; } fclose(flog); }}void Log(const char *pszFmt,...) { va_list argp; Lock(&cs_log); va_start(argp,pszFmt); LogV(pszFmt,argp); va_end(argp); Unlock(&cs_log);}//Log}int main(int argc,char * argv[]) { int i;#ifdef WIN32 InitializeCriticalSection(&cs_log);#else pthread_mutex_init(&cs_log,NULL);#endif for (i=0;i<10000;i++) { Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__); }#ifdef WIN32 DeleteCriticalSection(&cs_log);#else pthread_mutex_destroy(&cs_log);#endif return 0;}