2010-08-31 два проблема
by Vasil KolevИ малко по работа – занимавах се с два проблема тия дни, които заслужават малко внимание.
Единия е свързан с thread-ове, сигнали и libc I/O. Ситуацията излеждаше в общи линии по следния начин – един демон с няколко thread-а, които пишат в log, който пък се re-open-ва в един signal handler. Има един lock, който се ползва за друга синхронизация, колкото да направи нещата по-весели.
Накратко изводът е “не правете така”. В signal handler нищо не трябва да се прави, освен може би да се пипне някоя глобална променлива, ползвана като семафор, иначе се получава deadlock, който е бая сложен за откриване (виждате няколко thread-а, висящи във futex() и почти нищо друго), понеже и lock-овете съвсем не са ясни (понеже са вътре в libc, а семантиката на futex е бая крива, в man-а даже си пише – това иска и малко асемблер да се ползва, предназначено е за lib-ове, не за простосмъртни).
Вторият проблем оправих преди малко и е един от най-глупавите, в които съм се набивал (и съм си причинявал сам). Имаме в общи линии следния код:
int a,b,crap;
log=fopen("/path/to/log",a);
while (!feof(log))
{
// log format: 120102121 25 1024
// timestamp seconds bytes
fscanf(log,"%d %d %d",&crap,&a,&b);
// do something
}
който в общи линии обработва един log, обръща го в sql заявки и го насипва в една база. Изведнъж започна да не свършва работа – като в началото реших, че базата се претоварва и не успява да поеме всичките (около 800 000) заявки. След половин ден тестове (и няколко други неща за оправяне, с почивки) най-накрая открих проблема – в log формата изведнъж (е, не особено изведнъж, написано беше преди месец, сега случайно беше пуснато в действие) изведнъж се появило още едно поле, което води до fscanf да не прочете нищо и същевременно feof() да не познае, че файла е свършил.
Решенията са две – или да се проверява колко точно елемента е прочел fscanf(), или да се оправи какво точно се чете. За момента е второто, поне докато не си измисля малко по-хубав начин от първия.
Tags: работа
September 1st, 2010 at 13:37
най-смешното е, че водиш лекции по програмиране :)
September 1st, 2010 at 13:47
@abc, това, че водя лекции е смешно по кило други причини :) Иначе измряха безгрешните, които преподаваха, останаха такива като мене :)
(а и откъде мислиш научавам какво да обяснявам на студентите да не правят ?:) )
September 1st, 2010 at 14:35
ей ламер, fgets()/fread() + strsep() + strtol() … без да навлизам в подробности за глупостите, които си изписал по-горе :D
September 1st, 2010 at 14:39
while(getline(&line, &len, fp) != EOF) тъй ше свърши все някога :)
September 1st, 2010 at 14:48
@core-ix, аз не се възбуждам, като пиша код, та гледам да е по-кратък. Ако исках да си пиша краен автомат, щях това да направя :)
@Георги, да, това е по-чист вариант.
Иначе – ясно, че има поне още няколко проблема, например integer overflow, както и че ако ми подадат преебан вход ще се счупи бая сериозно (да не обяснявам как не проверявам fopen() кво ми връща и segfault-вам след това :) ). Хубаво е някой да обяснява как НЕ СЕ пише код, щото хора, дето обясняват кое е вярно – много, и повечето от тях се считат за пророци на бога на C-то или който-е-там-език и после ходи обяснявай, че не са съвсем прави.
September 1st, 2010 at 14:55
getline ще ти върне -1 дори да ти е невалиден стрийма .
September 1st, 2010 at 14:57
Обяснявам логика:
fread()/fgets(), за да вземеш поредната линия от файла
strsep(), за да разделиш отделните полета, съобразно избрани от теб делимитери
strtol() (вместо atoi()), за да имаш return value на база, на който да провериш дали конверсията е минала успешно
или иначе казано, ако беше ползвал подобна комбинация от функции нямаше да ги пишеш тия постове тук и кодът ти щеше да работи при добавяне на поле и пр.
Колкото до другото – sloppiness leads to low productivity … ‘щот си ламер :D
А, и една странична забележка, както беше подхвърлено, защо не земете да издадете една книжка “ManiaX Design Patterns – New structures and strategies for complex problem solving” ??? :D
September 1st, 2010 at 15:08
@core-ix, както казах, ако исках да напиша нещо такова, щях. Домързя ме :)
(иначе честно казано предпочитам специално за тоя тип неща (не-критични системи) нещата да гърмят видим, вместо да се оправят сами)
Обещавам да ти посветя една книга някой ден :) Ще напиша “на моя велик ментер core-ix” :)
(ментер оставям да си го преведеш сам :) )
September 1st, 2010 at 15:10
Ай лов ю бейби! Ай лов ю форевър! :D
September 1st, 2010 at 15:23
@core-ix, е не пред всички де. Пак три месеца ще ме обвиняват в зоофилство.