Я вот написал софтину, которая чекает мыла на валидатность. Она у меня тредовая. Кол. тредов указываешь. Каждый тред считывает определенное кол. бай с файла и чекает мыла на MX записи. Чекаю я через
res_search
функцию. Тестирование я проводил при 500 тредах, каждый тред считывал по 10кб данных с файла. Прикол в том, что если закоментировать кусок кода, который чекает на MX записи, то все пашет (файл при єтом парсится тредами и переписывается в другой). Если оставить этот кусок кода, то на середине проверки вываливается
Segmention fault Как это понять ?
Вот весь код :
#include <sys/types.h>
#include <stdio.h>
#include <pthread.h>
#include <g++/vector>
#include <g++/string>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <g++/iostream>
#include <sys/stat.h>
#include <unistd.h>
#include <g++/algorithm>
#define MAXTHREADCOUNT 500
#define MINTHREADCOUNT 1
#define STEPPOS 10240
void readData(char*, long, int);
void usage();
int emailParse(char* email, string& account);
void* thread_proc(void*);
long getFileSize(char*);
struct threaddata
{
long pos;
int id;
};
string account = " ";
long threadcount = 0;
char s_filein[128];
char s_filebad[128];
char s_filegood[128];
long itemindex;
long filesize = 0;
long filepos = 0;
pthread_t threads[MAXTHREADCOUNT];
threaddata MID[MAXTHREADCOUNT];
vector<string> V[MAXTHREADCOUNT];
int Free[MAXTHREADCOUNT];
vector<string> whitelist;
vector<string> badlist;
int main(int argc, char** argv)
{
for (int index=1;index<argc;index++)
{
if (!strcmp("-threadcount", argv[index])) threadcount = atoi(argv[index+1]); else
if (!strcmp("-bad", argv[index])) strcpy(s_filebad, argv[index+1]); else
if (!strcmp("-in", argv[index])) strcpy(s_filein, argv[index+1]); else
if (!strcmp("-good", argv[index])) strcpy(s_filegood,argv[index+1]);
}
if ((!threadcount) || (!strlen(s_filebad)) || (!strlen(s_filegood)) || (!strlen(s_filegood)))
{
usage();
return 1;
}
if (!((threadcount<=MAXTHREADCOUNT) && (threadcount>=MINTHREADCOUNT)))
{
usage();
return 1;
}
filesize = getFileSize(s_filein);
for (itemindex=0;itemindex<threadcount;itemindex++) Free[itemindex] = 1;
while (filepos<filesize)
{
for (itemindex=0;itemindex<threadcount;itemindex++)
{
if (Free[itemindex])
{
MID[itemindex].id = itemindex;
MID[itemindex].pos = filepos;
pthread_create(&threads[itemindex], NULL, &thread_proc, &MID[itemindex]);
filepos+=STEPPOS;
}
}
sleep(1);
}
for (itemindex=0;itemindex<threadcount;itemindex++) pthread_join(threads[itemindex], NULL);
return 0;
}
void usage()
{
printf("Usage : \n");
printf("$./a.out -in mails.txt -good good.txt -bad bad.txt -threadcount 50\n");
printf("Note, please %i<=threadcount<=%i\n",MINTHREADCOUNT, MAXTHREADCOUNT);
}
void readData(char* filename, long p, int id)
{
long size = 0;
char ch = 0;
char line[100];
FILE* f = fopen(filename,"r");
fseek(f, p, 0);
if (p) while ((ch!='\n') && (!feof(f))) fscanf(f,"%c",&ch);
V[id].clear();
while ( (!feof(f)) && (size<(STEPPOS+60)))
{
fscanf(f,"%s",line);
size+=(strlen(line) + 2);
if (size>(STEPPOS+60)) break;
if (emailParse(line, account))
{
if (account.length())
{
V[id].push_back(account);
}
}
}
}
int emailParse(char* email, string& account)
{
int index = 0;
while (index<strlen(email)) account[index] = email[index++];
account[index] = 0;
return 1;
}
void* thread_proc(void* parameter)
{
struct threaddata* data = (struct threaddata*)parameter;
Free[data->id] = 0;
if (data->pos>filesize)
{
Free[data->id] = 1;
return NULL;
}
unsigned char answer[PACKETSZ];
readData(s_filein, data->pos, data->id);
vector<string>::iterator itvec = V[data->id].begin(), itvecEnd = V[data->id].end();
int vsize = V[data->id].size();
for (int index=0;index<vsize;index++)
{
char* email = (char*)V[data->id][index].c_str();
char acc[32], dom[32];
int i = 0;
int p = 0;
while ((email[i]!='@') && (i<strlen(email))) acc[i] = email[i++];
acc[i] = 0;
i+=1;
while (i<strlen(email)) dom[p++] = email[i++];
dom[p] = 0;
int flag = 0;
string sdom = dom;
FILE* f=fopen("r.txt","a");
fprintf(f,"%s@%s\n", acc, dom);
fclose(f);
if (res_search(dom, C_IN, T_MX, static_cast<u_char*>(answer), sizeof(answer))>0) flag = 1;
if (!flag) if (res_search(dom, C_IN, T_MX, static_cast<u_char*>(answer), sizeof(answer))>0) flag = 1;
if (flag)
{
FILE* f=fopen(s_filegood,"a");
fprintf(f,"%s\n", email);
fclose(f);
} else
{
FILE* f=fopen(s_filebad,"a");
fprintf(f,"%s\n", email);
fclose(f);
}
}
Free[data->id] = 1;
return NULL;
}
long getFileSize(char* filename)
{
struct stat st;
FILE* f = fopen(filename,"r");
fstat(fileno(f), &st);
fclose(f);
return st.st_size;
}
А вот этот кусок кода у меня чекает на MX записи. Если его закоментировать то все Ок, иначе сегм. фаулт :
if (res_search(dom, C_IN, T_MX, static_cast<u_char*>(answer), sizeof(answer))>0) flag = 1;
if (!flag) if (res_search(dom, C_IN, T_MX, static_cast<u_char*>(answer), sizeof(answer))>0) flag = 1;
if (flag)
{
FILE* f=fopen(s_filegood,"a");
fprintf(f,"%s\n", email);
fclose(f);
} else
{
FILE* f=fopen(s_filebad,"a");
fprintf(f,"%s\n", email);
fclose(f);
}
С памятью я вроде нормально работаю, ну и с тредами верно обращаюсь.
Здравствуйте, alexora, Вы писали:
A>Я вот написал софтину, которая чекает мыла на валидатность. Она у меня тредовая. Кол. тредов указываешь. Каждый тред считывает определенное кол. бай с файла и чекает мыла на MX записи. Чекаю я через res_search
функцию. Тестирование я проводил при 500 тредах, каждый тред считывал по 10кб данных с файла. Прикол в том, что если закоментировать кусок кода, который чекает на MX записи, то все пашет (файл при єтом парсится тредами и переписывается в другой). Если оставить этот кусок кода, то на середине проверки вываливается Segmention fault Как это понять ?
A>Вот весь код :
A>[ccode]
A>#include <sys/types.h>
A>#include <stdio.h>
A>#include <pthread.h>
A>#include <g++/vector>
A>#include <g++/string>
A>#include <netinet/in.h>
A>#include <arpa/nameser.h>
A>#include <resolv.h>
A>#include <g++/iostream>
A>#include <sys/stat.h>
A>#include <unistd.h>
A>#include <g++/algorithm>
A>#define MAXTHREADCOUNT 500
A>#define MINTHREADCOUNT 1
A>#define STEPPOS 10240
For users of C and C++ compilers without support for the -pthread switch,
you must ensure that the C preprocessor symbol _REENTRANT is defined before
including any system header file. One way to accomplish this is to compile
the application as follows:
cc -c myprog.c -D_REENTRANT
То есть тебе нужны thread-safe версии библиотек. Вот такие три строки _перед_ всеми инклюдами тебе помогут
#ifndef _REENTRANT
#define _REENTRANT
#endif // _REENTRANT
или действительно задай этот define в опциях компиляции.
Здравствуйте, Ekin, Вы писали:
E>Здравствуйте, alexora, Вы писали:
A>>А по подробней можно узнать что за -D_REENTRANT
A>>Почему -pthread не катит ?
E>Опция -pthread должна катить, судя по докам. А что этот дефайн помог, а -pthread само по себе не помогло?
Дефайн _REENTRANT включат реентрантные версии функций и возможно структур. Правда, наверное, только при сборке библиотек, потому что я сейчас не нашел зацепок в хедерах.
Реентрантные функции, это те в которые можно зайти снова, когда другой вызов еще не вышел -- например при рекурсии или из другого треда. В частности, это значит, что эти функции не используют статичесие данные, если только они не константные или защищены мьютексом.
Бывает и вот такие смешные случаи нереентрантности в одном треде:
printf( "%s -> %s\n", inet_ntoa(ip_src), inet_ntoa(ip_dst));
напечатает всегда два раза адрес ip_dst, несмотря на намерение вложенное в этот принт программистом

)
(потому что библиотечная функция inet_ntoa очевидно возвращает указатель на свой статический буфер.)
Иногда реентрантность дорго обходится по памяти и времени. А треды пользуют все же не часто. Поэтому и бывают две версии библиотек.
Здравствуйте, alexora.
Вы писали 2 июня 2004 г., 2:00:53:
a> a> if (res_search(dom, C_IN, T_MX, static_cast<u_char*>(answer), sizeof(answer))>0) flag = 1;
a>
а если попробовать заменить этот код, примерно
такимАвтор: butcher
Дата: 17.03.04
?
--
С уважением, butcher
Posted via RSDN NNTP Server 1.8
Здравствуйте, alexora, Вы писали:
A>Я вот написал софтину, которая чекает мыла на валидатность. Она у меня тредовая. Кол. тредов указываешь. Каждый тред считывает определенное кол. бай с файла и чекает мыла на MX записи. Чекаю я через res_search
функцию. Тестирование я проводил при 500 тредах, каждый тред считывал по 10кб данных с файла. Прикол в том, что если закоментировать кусок кода, который чекает на MX записи, то все пашет (файл при єтом парсится тредами и переписывается в другой). Если оставить этот кусок кода, то на середине проверки вываливается Segmention fault Как это понять ?
A>Вот весь код :
A> pthread_create(&threads[itemindex], NULL, &thread_proc, &MID[itemindex]);
A> filepos+=STEPPOS;
A> for (itemindex=0;itemindex<threadcount;itemindex++) pthread_join(threads[itemindex], NULL);
Появилась еще одна мысль. В дефолтной сборке ядра линукса максимальное число тредов на процесс 256. Ты не проверяешь создался у тебя тред или нет, то есть фактически ты не знаешь проинициализировлаись ли у тебя threads[itemindex], а потом вызываешь pthread_join на нем. Когда ты комментируешь res_search треды быстро заканчиваются, и их число не успевает превысить 256. Когда же ты резольвишь, треды работают долго и на 257 треде твоя прога валится.
если ты в линуксе работаешь и под bash-ом, ты можешь сделать ulimit -с unlimited, потом после того как прога свалится и скинет кору сказать gdb myprog core, а уже в gdb сказать bt, конечно дебаггером отлаживать многотредовые проги практически невозможно, но ты увидешь все-таки в каком месте прога свалилась, особенно если компилил с -g опцией