nixp.ru v3.0

16 января 2017,
понедельник,
22:27:36 MSK

DevOps с компанией «Флант»
df_0903 написал 5 апреля 2004 года в 21:05 (587 просмотров) Ведет себя неопределенно; открыл 6 тем в форуме, оставил 17 комментариев на сайте.

У меня есть одна довольно сложная программка. В ней пользователь

может запускать detached потоки, каждый из которых делает fork и, затем,

exec или popen, затем через waitpid ждет окончания дочернего процесса,

ловя при этом вывод 'ребенка’. Все вроде бы замечательно, но иногда

поток зависает намертво, иногда даже основной поток тоже зависает.

Не могу понять почему. Никакой закономерности.

Longobard

Сырцы в студию. Желательно с коментами.

df_0903

Попробую описать подробнее

вот примерные исходники

#ifdef linux

#include

#define WAIT_FLAGS __WNOTHREAD

#else

#define WAIT_FLAGS 0

#endif

typedef void* (*thread_func)(void*);

//вспомогательная структура для передачи параметров потоку

struct CallInfo

{

const char* command;

bool Wait;

};

//функция вызова(создания) detached потока

thread_call(thread_func funcp,void* argp,int sched_type,int priority)

{

pthread_attr_t attr;

pthread_attr_t* attrp=&attr;

pthread_t tid=(pthread_t)-1;

if(pthread_attr_init(attrp)==-1)

attrp=NULL;

else

{

pthread_attr_setdetachstate(attrp,PTHREAD_CREATE_DETACHED);

pthread_attr_setscope(attrp,PTHREAD_SCOPE_SYSTEM);

if(sched_type!=RTHREAD_SCHED_OTHER)

{

pthread_attr_setschedpolicy(attrp,sched_type);

struct sched_param sched;

if(!pthread_attr_getschedparam(attrp,&sched))

{

sched.sched_priority=priority;

pthread_attr_setschedparam(attrp,&sched);

}

}

}

pthread_create(&tid,&attr,funcp,argp);

return tid;

}

//функция потока

void* process_launcher(CallInfo* oi)

{

if(!(oi->Wait)

{

int status;

char* shell;

pid_t pid=fork();

switch(pid)

{

case 0: if(!(shell = getenv( «SHELL» )))

shell=«/bin/sh»;

if(execl(shell,shell,«-c»,command.text(),(char*)NULL)==-1)

::exit(errno);

exit(0);

case -1: break;

default: waitpid(pid,&status,WAIT_FLAGS);

}

}

else

{

char tmp[PATH_MAX+NAME_MAX];

make_tmp_file_name(tmp);

int status=0;

char* shell;

if(!(shell = getenv( «SHELL» )))

shell=«/bin/sh»;

char tmp2[PATH_MAX+NAME_MAX];

make_tmp_file_name(tmp2);

FILE* fo=fopen(tmp2,«w+»);

fprintf(fo,«%s\n»,command.text());

fclose(fo);

char* argv[3]=

{

shell,

tmp2,

NULL

};

pid_t pid=fork();

switch(pid)

{

case 0: ::freopen(tmp,«w»,stdout);

::freopen(tmp,«w»,stderr);

signal(SIGTTIN,SIG_IGN);

if(execv(shell,argv)==-1)

{

perror(«execv»);

::exit(errno);

}

exit(0);

case -1: perror(«fork»);break;

default: waitpid(pid,&status,WAIT_FLAGS);

}

//Дальше читаем файл tmp

. . .

}

return NULL;

}

//примерный алгоритм работы

int main()

{

CallInfo oi1={"ps xm»,true};

CallInfo oi2={"cat /proc/interrupts»,true};

CallInfo oi3={«kedit»,false};

thread_call(process_launcher,&oi1,RTHREAD_SCHED_OTHER,0);

thread_call(process_launcher,&oi2,RTHREAD_SCHED_OTHER,0);

thread_call(process_launcher,&oi3,RTHREAD_SCHED_OTHER,0);

. . .

//do something

. . .

return 0;

}

anonymous

Лучше поздно, чем никогда:))))

Есть такой прикол: размер пайпа ограничен, то бишь, если в него попытаться записать слишком много, процесс повиснет до тех пор, пока из пайпа не начнут читать. Насколько я понял твой код, потомок пишет в пайп, в это в ремя родитель его ждёт waitpidом, потом потомок выходит, а родитель начинает читать из пайпа. Может возникнуть такая ситуация: потомок переполнил пайп и ждет, что из него начнут читать, а родитель ждёт, когда потомок выйдет…… И всё висит.

df_0903

Спасибо за информацию. Я об этом не задумывался. Но ошибка была в другом.

Гонки в mutex-ах.

ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.