df_0903
написал 5 апреля 2004 года в 21:05 (1407 просмотров)
Ведет себя
неопределенно; открыл 6 тем в форуме, оставил 17 комментариев на сайте.
У меня есть одна довольно сложная программка. В ней пользователь
может запускать detached потоки, каждый из которых делает fork и, затем,
exec или popen, затем через waitpid ждет окончания дочернего процесса,
ловя при этом вывод 'ребенка’. Все вроде бы замечательно, но иногда
поток зависает намертво, иногда даже основной поток тоже зависает.
Не могу понять почему. Никакой закономерности.
Последние комментарии
- OlegL, 17 декабря в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
ecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.
Сырцы в студию. Желательно с коментами.
Попробую описать подробнее
вот примерные исходники
#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;
}
Лучше поздно, чем никогда:))))
Есть такой прикол: размер пайпа ограничен, то бишь, если в него попытаться записать слишком много, процесс повиснет до тех пор, пока из пайпа не начнут читать. Насколько я понял твой код, потомок пишет в пайп, в это в ремя родитель его ждёт waitpidом, потом потомок выходит, а родитель начинает читать из пайпа. Может возникнуть такая ситуация: потомок переполнил пайп и ждет, что из него начнут читать, а родитель ждёт, когда потомок выйдет…… И всё висит.
Спасибо за информацию. Я об этом не задумывался. Но ошибка была в другом.
Гонки в mutex-ах.