Мне очень трудно отлаживать многопоточное приложение C, в которое я внес несколько изменений. Мне не удалось использовать GDB для выявления проблемы (дополнительную информацию см. в приведенном ниже коде).
Следующий код взят из одной из задач, которая открыта в собственном потоке. Я вырезал большую часть кода после проблемы.
void tskProcessTenMinuteTables(void *input)
{
/* Check the minute as soon as we start. If we're started on a ten min
* boundary, sleep for one minute.
*/
time_t now;
time_t wakeup;
struct tm *next_tick_ptr;
now = time(NULL);
next_tick_ptr = localtime(&now);
/* returns a time struct populated w/ next ten min boundary */
GetNextTenMinBoundary(next_tick_ptr);
wakeup = mktime(next_tick_ptr);
sleep(2); /* Without this sleep, the following if() was always true. */
if(next_tick_ptr->tm_min % 10 == 0)
{
fprintf(stderr, "On tenmin boundary on initialization.. task sleeping for 60 seconds.\n");
/* debug statements to test the cause of segfault. */
fprintf(stderr, "NOM NOM NOM\n");
printf( "Test%d\n", 1);
fprintf(stderr, "Test%d\n", 2); /* <~~~ This statement is the guilty party */
sleep(60);
}
/* Main loop. Every loop besides the tick itself will consist only
* of a call to time and a comparison of current stamp with wakeup.
* this should be pretty light on the processing side.
*
* Re-implement this as a sleep/awake with a signal in the future.
*/
while(1)
{
now = time(NULL);
if( now >= wakeup )
{
fprintf(stderr, "Triggered 1.\n");
fprintf(stderr, "Triggered 2.\n");
char statement[150];
fprintf(stderr, "Triggered 3.\n");
sprintf(statement, "SELECT ten_min_end(%d::int2)",GetTenMinPeriodNumber());
fprintf(stderr, "Triggered 4.\n");
DBCallStoredProcedure(statement);
fprintf(stderr, "Triggered 5.\n");
}
}
Причина в попытке использовать fprintf с вариативными (?) аргументами. Вызов его без чего-либо, кроме шаблона, работает. Функции Printf с аргументами или без них.
fprintf(stderr, "Hi #%d.\n", 1); <~~ segfault
fprintf(stderr, "Hi #1.\n"); <~~ works
printf("Hi #%d.\n", 1); <~~ works
printf("Hi #1.\n"); <~~ works
При запуске в gdb я получаю следующий выброс до того, как gdb перестанет отвечать. Для завершения требуется kill -9.
$gdb ir_client
(gdb) r
Starting program: /home/ziop/Experimental_IR_Clients/ir-10-20/IR_Client/obj-linux-x86/ir_client
[Thread debugging using libthread_db enabled]
[New Thread 0xb7fe5b70 (LWP 32269)]
[New Thread 0xb7fc4b70 (LWP 32270)]
(032266 - -1208067216) 20-Oct-2010 10:56:19.59 - IR_Client_ConnectCmdPort - Socket connected.
[New Thread 0xb7ffdb70 (LWP 32272)]
(032266 - main thread) 20-Oct-2010 10:56:19.59 - sl_exit - Exiting thread with code 0.
On tenmin boundary on initialization.. task sleeping for 60 seconds.
NOM NOM NOM
Test1
Я новичок в C, так что это может быть что-то очевидное. Моей первой мыслью было то, что небуферизованный вывод не является потокобезопасным, но fprintf всегда завершается успешно, если не передается переменная. Напуганность Pthread по-прежнему остается моим главным подозреваемым. К сожалению, я застрял с архитектурой на данный момент.
Заранее спасибо.
localtime
. Он использует одну и ту же память для структурыtm
для каждого потока. Вы должны защитить его с взаимным исключением, скопировать его или использовать, а также выпустить, если хотите избежать гонок. - person slezica   schedule 20.10.2010printf("thread stk = %p\n", &input);
иflush(stdout);
в начало функции потока и зафиксируйте вывод (надеюсь, это ничего не сломает). Затем снова запустите Valgrind и посмотрите, до чего вы пытаетесь расширить стек, и как это соотносится со значением в моем операторе печати. Материал cat /proc есть на случай, если вам понадобится дальнейшее расследование. - person nategoose   schedule 21.10.2010cat /proc/self/maps
в середине вашего потока, чтобы увидеть, что, если адреса в данных об ошибках вообще имеют смысл. - person nategoose   schedule 21.10.2010pthread_create
? Вы создали его с какими-либо атрибутами (второй аргумент)? - person nategoose   schedule 21.10.2010job_create
. Если стек предварительно выделен вызывающей сторонойjob_create
, убедитесь, что он выделен правильно и соответствует размеру. Я думаю, что должно быть много стека потоков, если в системе постоянно не хватает памяти. - person nategoose   schedule 21.10.2010