Ez már kezd az agyamra menni... Hogy kell lekérni Linux alatt a child visszatérési értékét, ha pipe is van? Rohadtul nem úgy működik, ahogy a man page állítja!
Pipe (és WNOHANG) nélkül minden okés:
ret = 0; if(!(pid = fork())) { ret = 1; printf("child ret %d\n", ret); exit(ret); } else if(pid > 0) { waitpid(pid, &ret, 0); printf("parent ret %d\n", ret); }
Kimenet:
child ret 1 parent ret 1
Na de nekem az kellene, hogy a gyerek futtasson le egy parancsot, ha nem sikerül, akkor írja ki a hibát, és mindezt a szülő pipe-al olvassa, ugyanakkor a visszatérési érték is kéne, hogy sikerült-e a futtatás.
Teljes példa:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> int main(int argc, char **argv) { char output[4096]; int stdoutpipe[2], l, ret = 0; pid_t pid; if(pipe(stdoutpipe) < 0) { fprintf(stderr, "unable to create pipe?\n"); return 1; } if(!(pid = fork())) { close(1); close(2); close(stdoutpipe[0]); dup2(stdoutpipe[1], 1); dup2(stdoutpipe[1], 2); close(stdoutpipe[1]); #ifdef NOTOKAY ret = system("echosaaa"); #else ret = system("echo"); #endif if(errno) perror(NULL); printf("child ret %d\n", ret); exit(ret); } if(pid > 0) { close(stdoutpipe[1]); do { if((l = read(stdoutpipe[0], output, 4096)) > 0) write(1, output, l); } while(waitpid(pid, &ret, WNOHANG) != pid); close(stdoutpipe[0]); } else { fprintf(stderr, "unable to fork?\n"); close(stdoutpipe[0]); close(stdoutpipe[1]); } printf("parent ret %d exit %d\n", ret, WEXITSTATUS(ret)); (void)argc; (void)argv; return 0; }
Ez konstans 0-át ad vissza, akármi is a gyerek exit() paramétere.
$ gcc aaa.c -o aaa; ./aaa child ret 0 parent ret 0 exit 0 $ gcc -DNOTOKAY aaa.c -o aaa; ./aaa sh: line 1: echoaaa: command not found child ret 32512 parent ret 0 exit 0
Magyarán a waitpid NEM állítja a státuszt, akkor sem, amikor a gyerek pidjével tér vissza, holott a man page szerint kéne neki. Példától függően vagy konstans -1, vagy konstans 0 lesz minden exit() értékre a ret.
WTF? Miért nem adja vissza a gyerek státuszát a watpid, ha WNOHANG opcióval hívódott?
És ha ez normális, akkor hogy a francba kell lekérni a gyerek státuszát, ha olvasni is akarja az ember a kimenetét??? Alaposan átolvastam a man page-eket, nagyon nem így kéne működnie! Rengeteg példát is áttúrtam, de bakker, azok vagy csak a visszatérési értéket kérik le, vagy a kimenetet, de egyik sem mindkettőt!
Ami leírást meg github-ot találtam, ott mindenhol azt írják, így működnie kéne. De mégsem működik! Arról sehol nem szól fáma, hogy a waitpid hibás értéket adna vissza a status paraméterben.
Stackoverflow-val sem kerültem közelebb a megoldáshoz, ezt találtam, ami hasonló (neki is a waitpid()-el van baja, ha WNOHANG meg van adva, mondjuk ő 0-át kap vissza), habár ez epoll-al is meg van spékelve. A megoldási javaslat: "One possible implementation is to repeat waitpid(..., WNOHANG) until it returns the expected PID", na de hát én pont eleve ezt csinálom! Akkor WTF?
Hozzászólások
A man leírja, hogy a status értékét a WIFEXITED és WEXITSTATUS makrókkal kell nézni.
Osz mire mész vele, ha mindkét esetben csupa 1-es bit a status??? Gyerek "exit(0)", szülő status=0xFFFFFFFF; gyerek "exit(1)", szülő status=0xFFFFFFFF!!!
Tisztában vagyok vele, hogy alsó 8 bitnek a visszatérési értéket kéne tartalmaznia, ezt írja a man is, de rohadtul nem azt tartalmazza, pont ez a bajom! Azt nem tudom, hogy miért nem. Nincs semmi signal, az exit()-nek meg minden nyitott fájlleírót be kell zárnia, de manuálisan is bezárom őket.
Tegyél bele hibakezelést. Ráfut a break-re a ciklus? A waitpid negatív értéket ad vissza? Errno mit mond? Stb.
Ezeken már rég túl vagyok, nyilvánvaló dolgokért nem nyitottam volna topikot.
Nem.
Nem. 0-át ad vissza amíg fut a gyerek, amikor végzett, akkor meg a gyerek pid-jét.
0.
A parent oldalon valaszd kulon a do/while() loopot es a waitpidet. Ha child lezarta az stdout-jat mert kilepett exit()-tel akkor a parent oldali read() nullaval ter vissza. Ekkor megszakitod a while() ciklust, majd ezutan egy blocking waitpid()-del megnezed az exit statust:
ezt most csak ugy vakon beirtam, de ugy remlik hogy igy szoktam csinalni ezeket...
Ugye a do-while megoldasoddal az a gond hogy a read()==0 esetben megszakitod a ciklust, igy az a waitpid() nem is fog lefutni valojaban... es ha blocking read()-dal is meg nonblocking waitpid()-del is tesztelsz akkor az valojaban egy race condition ha jobban belegondolok.
Már próbáltam így sem működik. Ilyenkor mindig 139-et ad vissza, függetlenül attól, hogy mi volt a gyerek exit() paramétere.
Ahogy egmond kollega is irja lentebb: tudsz bemasolni ide egy minimal working example-t?
A while-ban való vizsgálatod miatt nem derül ki, hogy mi miatt nem a pid-del tér vissza, azaz 0-val vagy -1-gyel:
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
De kiderül, és már meg is írtam.
szerk.:
Én úgy csinálnám, hogy - mivel úgyis van pipe -on keresztüli kommunikáció - a child írjon bele a pipe-ba minden infót, amit a parent-nek tudnia kell. Pl. ebben az esetben a saját pid-jét és a system() visszatérési értékét.
s az output, ott van az exit code:
Már írtam, ha nincs pipe, minden jó... Próbáld meg pipe-al olvasva!
megy az pipe-pal is:
Nem is megy. És minek az fcntl meg az a tetves sok sleep? Felejtős, a gyerek által hívott programban nincs sleep.
Te már megint hazudsz a forrásodról. Nem ez az első eset!
ott az output, sleep nélkül... mi a túró nem megy?
na, elmész te a jó édesanyádba, akkor... tanulj meg programozni... balfasz@hup
Nem mintha vitapartnered stílusa rendben volna, de azért Te is megéred a pénzed.
Írsz egy busy loop-ot mint javasolt megoldás, ami teljesen fölöslegesen ébreszti fel a processzt tizedmásodpercenként akkor is ha amúgy az ég-világon semmi nem történik, és a legvégén akár tizedmásodperc (várható értékben annak fele) késleltetéssel veszi észre hogy kilépett a gyerek.
Az a programozás tanfolyam mindkettőtöknek jót tenne!
Nulladik: tibyke nevében a -val, -vel ragot tessék átismételni!
Első: Minimal reproducible example-t mutass! Kiegészítettem a kódodat működőképesre, de egyrészt miért kéne ezzel időt töltenie annak aki segíteni akar neked?, másrészt nem ugyanazt kapom amit te. Olyan apróságok, mint például az "l" változó típusa, előjeles vagy előjel nélküli, alulcsordul-e a -1, hibás összehasonlítást eredményezve, is számíthat.
Továbbiak: A gyerekben printf() és perror() függvénnyel írsz a kimenetre / hibakimenetre, amik már a pipe-ra vannak átrakva. Hogy jelenik meg a "child ret 0" sor? Nem értem. Hacsaknem a csinalvalamitakimenettel() függvény átlapátolja, de akkor miért nem lapátolja át a "sh: line 1: ./hibasparancs: Permission denied" sort is? Biztos vagy benne, hogy a(z amúgy működésképtelenre csonkított) programod kimenetét pontosan mutattad meg nekünk?
A system(), meg a legtöbb függvény, tudtommal nem ígéri meg hogy siker esetén az errno-t békén hagyja, vagy nullázza. (Lehet hogy tévedek amúgy, a man page nem dokumentálja ezt.) (Kivételes esetben van csak értelme kézzel nullázni az errno-t. Nézz rá mások programjaira, (szinte) sose látsz ilyet, elég gáz lenne ha úgy kéne programozni hogy minden függvényhívás előtt az errno-t nullázni kellene kézzel.) Először a ret-et vizsgáljuk, és csak ha az hibát jelez akkor nézünk rá az errno-ra.
Na de a lényegre ránézve: Az, hogy a gyerek processz kilép, és az, hogy a pipe-on EOF-ot kapsz, az két teljesen független esemény, akármelyik irányba sok-sok idő eltelhet köztük.
Ha a gyerek szül magának egy gyereket (unokát a fő programod szemszögéből), akkor az eredeti gyerek kiléphet, a pipe még él és virul és bonyolíthat további forgalmat, miközben a waitpid() már jelenti hogy kilépett. Ugyanez megtörténhet úgy is, hogy a fájlleírót átpasszolja egy másik processznek (perverz, ritkán látott, de működőképes dolog).
Ha viszont a gyerek bezárja a pipe író végét, akkor még vígan élhet sokáig, a pipe olvasó vége EOF-ot kap.
Ha csak "simán" kilép a gyerek és nem csinált semmi szokatlant, akkor a fentiek miatt olyan race condition-ök vannak, hogy nem tudhatod, hogy a két esemény közül melyiket észleli elsőként a szülő processzed, esetleg az egyik forgatókönyv történik az esetek 99.99%-ában, a másik pedig 0.01%-ban, sok sikert az ilyen hibák utólagos levadászásához :)
A programod amúgy mindkét sorrendet hibásan kezeli. Koncepcionálisan nem gondoltad végig hogy mit akarsz csinálni.
Ha előbb veszed észre hogy kilépett a gyerek, akkor a pipe-ban ott ragadhat adat, amit sose olvasol ki. Például a gyerek kiír egyben 5kB-ot és rögtön kilép, a szülő beolvas 4kB-ot majd látja hogy kilépett a gyerek és nem olvas tovább.
Ha meg előbb veszed észre az adat végét, vagyis a read() visszatérési értéke 0, akkor kiugrasz a ciklusból, a waitpid() le se fut egyszer se, a pid-ben marad ami benne volt. Ez az amibe beleütközöl, szerintem.
> hogy a francba kell lekérni a gyerek státuszát, ha olvasni is akarja az ember a kimenetét???
Először legyen egy pontos specifikációd, hogy mit is szeretnél csinálni az imént említett esetekben. Például ha tudod hogy nem lesz unoka (vagy ha esetleg lesz, oké ha őt is meg kell várnod), akkor először olvass EOF-ig, utána jöhet a waidpid.
Sajnos egyébként nincs igazán jó általános válasz. Terminál emulátor programok szenvednek is emiatt. Egyrészt elvárás, hogy kilépjen, amint a gyerek kilépett, akkor is ha van unoka aki elvileg még írhat később a terminálra. Másrészt elvárás, hogy a gyerek összes kimenetét mindenképp feldolgozza - ez nem fontos akkor ha rögtön be is záródik az ablak, de fontos ha a terminál esetleg úgy van beállítva hogy nyitva tartsa az ablakot, vagy új shell-t indítson, vagy fontos hogy accessibility szoftver felolvassa a teljes szöveget stb. A luit program a -x kapcsolóval a felhasználóra bízza hogy kétféle működés közül válasszon: a gyerek kilépése számítson (adatvesztés lehetséges) vagy a csatorna bezárása számítson (unoka fogva tarthatja a vonalat). A VTE-ben (GNOME Terminal és társai) igazi fekete mágiát alkalmazunk: ha a gyerek kilépett, akkor még olvasunk legfeljebb 64kB-ot nem blokkoló módon, de abbahagyjuk az olvasást ha épp nincs adat: ezzel a módszerrel tuti (ööö... szinte tuti) kiolvasunk mindent amit a közvetlen gyerek írt, hiszen ha már kilépett akkor új cuccot már nem írhat, a régi meg legfeljebb 12kB körül lehet, kábé ekkora a kernelben a terminál vonal puffermérete; viszont ha van még unoka aki írhat a továbbiakban akkor arra nem várunk, ő már nem érdekel minket.
Mindenhol jól irtam! Idézd be, hogy mire irogatsz, ha kaffogni akarsz!
Azt tettem, csak a nyilvánvalót hagytam ki, hogy ne terelje el a lényegről a figyelmet.
Kurvára tök mindegy ebben a példában, mert a read csak egyetlenegyszer fut le és pozitív értéket ad vissza, de már írtam ezt... Egyébként meg a default C típus, tessék felcsapni a C szabványt és kikeresni, mi a default típus.
Na de a lényeg, ez tök nyilvánvaló, a kérdés nem is ez volt, hanem az, miért ad vissza a waitpid -1-et státusznak, amikor a gyerek kilép.
Ekkora bullshitet rég olvastam. Konkrétan 0 segítőgészség van az egész posztodban, csak ömlengés és digitális szemét. (Tisztázzuk, nincs race condition, egyáltalán, tudod, mi az? A waitpid a gyerek pid-jét adja vissza, arra lép ki a ciklus, de már leírtam ezt százszor.).
Nem tőled fog érkezni a megoldás, ebben egész biztos vagyok! >P
Örülök hogy segíthettem! Szívesen, máskor is!
Nem segítettél, csak zajt generáltál.
Így van; erre a hordozható megoldás a ppoll() / pselect(). A SIGCHLD-ot elkapjuk, de a programban végig maszkolva (blokkolva) tartjuk, csak a pselect / ppoll oldja fel ideiglenesen. Így tudunk multiplexelni a pipe IO-ra és a SIGCHLD-ra egyszerre. A SIGCHLD handler-ben max. egy volatile sig_atomic_t globális változót állítunk. A ppoll / pselect után lehet read(), write(), waitpid(). A waitpid()-nek nem kell WNOHANG (csak akkor hívjuk meg, ha volt SIGCHLD delivery a ppoll-on / pselect-en belül). Minimum a write()-nak viszont így is kell az O_NONBLOCK, mivel a ppoll / pselect már akkor is írhatóságot jelez pipe-on és named FIFO-n, ha csak PIPE_BUF byte-nyi hely van a pipe buffer-ben, viszont a write O_NONBLOCK nélkül pipe-on és named FIFO-n nem végez részleges írást, csak teljes buffert ír ki.
Idézek FreeBSD alól. (Kiemelés tőlem.)
$ man ppoll pselect
STANDARDS
The poll() function conforms to IEEE Std 1003.1-2001 (“POSIX.1”). The
ppoll() is not specified by POSIX. The POLLRDHUP flag is not specified
by POSIX, but is compatible with Linux and illumos.
STANDARDS
The pselect() function conforms to IEEE Std 1003.1-2001 (“POSIX.1”).
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
A SUSv4 Issue 8-ban, más néven POSIX.1-2024-ben már benne van a ppoll():
A pselect() tényleg régebb óta hordozható; a SUSv3-ban (POSIX.1-2001-ben) benne van:
(A fejlécben 2004-et fogsz látni; az csak annyit jelent, hogy a Technical Corrigenda 1 és 2 bele van olvasztva.)
A POSIX vs. Single Unix Specification nevezéktanról és verziókról bővebben:
Elismerem, némileg túlzás volt a 2024-esre azt mondanom, hogy hordozható... Pár éven belül hordozhatónak fog számítani, ahogy a POSIX-nak (névlegesen vagy hivatalosan) megfelelni akaró OS-ek fokozatosan támogatni kezdik. Addig lehet pselect()-et használni, az ismert hátrányaival ((1) az fd_set adatszerkezet általában nem gyors, (2) nagyon kell figyelni arra, hogy ha (fd >= FD_SETSIZE), akkor fd nem használható az FD_* interfészekkel, és így a pselect()-tel sem).
Teljes példa (de aki ennélkül nem érti a kérdést, attól aligha várható megoldás, csak megjegyzem...):
Ez konstans 0-át ad vissza, akármi is a gyerek exit() paramétere.
Magyarán a waitpid NEM állítja a státuszt, akkor sem, amikor a gyerek pidjével tér vissza. Jól látszik, hogy az az érték marad benne, ami volt.
Szóval a kérdés, hogy teljesen tiszta legyen mindenkinek: hogy kell egy gyerek processz kimenetét ÉS visszatérési értékét is megszerezni a szülőben?
angyalbegyerő, mi lenne, ha lekezelnéd azt az esetet, amikor 0-t ad vissza a waitpid?
Seggarc, le van már kezelve. Tanulj meg C-ül. Segítek: "if(pid > 0) { ..." és "......waitpid(pid, &ret, WNOHANG) != pid);".
s az leesett-e, angyalom, hogy 32512 az 0x7F00... az alsó fele 0... s neked azért lesz 0 a statusod
tedd csak oda bele, az exit elé, hogy ret = 123;
szívesen
Nicsak-nicsak, egy MRE amely nem ekvivalens az első postolt verzióval. Ugyanis a do cikluson belüli break kikerült. [Szerk: látom, azóta az eredeti postból is, így az eddig rá érkezett kommentek egy része nem igazán értelmezhető.]
A legeslegelső komment amit kaptál rámutatott egy hibára: a W* makrók hiányára. Visszadobtad a labdát azzal, hogy az nem oszt, nem szoroz, és emiatt hibásan hagytad azt a kódrészletet. Többen - köztük én - megmutattuk, hogy más hibák is vannak a kódodban.
Ezen más hibák közül egyhez hozzányúltál, a break eltűnt. És lám-lám most már nem csupa 1-es bit a gyerek visszatérési értéke.
Lehet hogy csak össze kéne raknod a puzzle-t? Hogy a kódodban több hiba is van, melyeket - mily meglepő - mindet javítani kéne? És esetleg nem zsigerből, fantasztikus tapasztalatoddal és rálátásoddal, remek minőségű kódodat lebegtetve lehülyézni azokat akik a több hibát nem mindet egyszerre veszik észre??
Nezd meg ezt: exit(ret); => exit(WEXITSTATUS(ret));
Igen, valóban ez az alapvető hiba a programban:
A két függvény specifikációja (kiemelés tőlem):
Tehát ha úgy hívjuk meg az exit()-et, hogy utána waitpid()-del akarjuk lekaszálni, akkor a 0..255 tartományba eső értéket "érdemes" neki adnunk. Ezt a feltételt a system() közvetlen visszatérési értéke pedig nem elégíti ki. (A debug kimenetből látszik, hogy a system() visszatérési értéke közvetlenül 32512; ahogy Micsa írta is, 0x7F00.)
Tehát a system() és az exit() között kell egy WIFEXITED() + WEXITSTATUS().
Ebből pedig kiderül a nagyobb probléma is: ebben a megközelítésben azt nem tudjuk visszaadni a parent-nek, ha a system() visszatérési értéke WIFSIGNALED()+WTERMSIG()-nek megfelelő (vagyis
a gyerek shell-gyerekének gyereke szignállal ért végeta gyerek shell-gyereke szignállal ért véget).Erre az intézményesített workaround / konvenció az, hogy az exit status-ban nem használunk 8 bitet, hanem csak 7-et; tehát normál (nem szignálos) befejeződésre minden utility 0-127 közötti értéket ad vissza. (Pontosabban 0-125 közöttit, ugyanis a 126-ot és a 127-et speciális értékeknek tekintjük.) És ha a system() azt mondja, hogy WIFSIGNALED(), akkor a gyerek azt az exit()-en keresztül úgy közli, hogy 128 + WTERMSIG(). (Érdekesség, hogy a legkülső szülő pl. a 128+11=139-es értékből nem tudja megkülönböztetni, hogy a gyerekben a system() által forkolt shell halt meg SIGSEGV-vel, vagy pedig a nevezett shell-nek a gyereke (a példában az echo). Utóbbi esetben a system() által índított shell végzi el a 128+WTERMSIG() összeadást, és a gyerek ezt az értéket csak továbbítja (mivel WIFEXITED()); előbbi esetben az összeadást a gyerek végzi el (mivel WIFSIGNALED())).
nem, itt az az alapvető hiba, hogy egyesek szociális képességeivel majorális problémák vannak...
Ötletnek nem rossz, de nem erről van szó. Ha lecserélem "if(errno) ret = 255;"-re a gyerekben, akkor sem jó értéket ad vissza a waitpid.
(szerk. a "-1 == status" hiányzott abból, amit először paste-eltem)
Bocsánat, ha elvesztettem a fonalat, de ha arra gondolsz, hogy az "if(errno) perror(NULL);"-t cseréled le "if(errno) ret = 255;"-re a topiknyitóban, az nem fogja a ret-et felülírni, mert a system()-nek nem kötelessége felülírni az errno-t, ha a child-ot sikerült elindítani, és az exit status-át begyűjteni.
Mondjuk nem azt javasolta apal, hogy:
rakjál oda, hanem azt, hogy:
legyen ott. Én kipróbáltam a módosítást, és működött:
De persze kereshetjük a megoldást a "dinamikusan linkelt függvénykönyvtár destruktorában".
🍿 azok a fránya makrók újra támadnak
// Happy debugging, suckers
#define true (rand() > 10)
Erdemben nem tok hozzaszolni, mert hala istennek nem vagyok programozo de az altalanos, h ti igy szivjatok egymas veret? :D:D (monduk a legdurvabb, h a kerdezo, aki segitseget ker ugye, hogy olt mindenkit...)
Egyiket sem kell félteni...
En is ugy latom :)
Hosszú múltra tekint vissza micsa trollkodása. Ha durvánnak tűnne, amit írtam, az csak emiatt lehetséges. Aki rendesen irogat és nem trollkodni próbál, annak mindig rendesen válaszolok én is.
Jellemző micsára, hogy odapofátlankodik a topikjaimba, majd tökéletes hozzánemértésről téve tanubizonyságot hülyeségeket ír, hazudozik, és nemegyszer forráskódot is megpróbált hamisítani már, mikor leplezni igyekezett a hazugságait.
Persze hazug embert könnyebb utolérni, mint a sánta kutyát.
abban a threadben mindenki látta, hogy félrebeszélsz tata... én nem hamisítottam semmit, te nem voltál képes megérteni, ami oda le lett írva, erről én nem tehetek
most is adtam neked egy működő kódot, erre elkezded a trollkodást... tudod: ilyenek az idióták.. más is megmondta már neked: balfasz@hup
te nem érdemled meg, hogy veled normálisan beszélgessen az ember
menj ügyesen, ápolgassad a nagy pofádat és a nagy egodat, itt már nagyon sok ember előtt lejárattad magad...
[off]
*pipe-pal, *Stackoverflow-val
Lemaradt a:
t
A Stackowerflow szerintem *erre* rossz példa, mert ott ezek szerint Stackowerflow-lal kéne legyen :-)
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
:(
A leírás szerint helyesen írtam. Pipe ejtése "pájp", tehát "az utolsóként kiejtett mássalhangzóhoz hasonul", azaz "pal" kell legyen. Hasonló a helyzet a "Stackoverflow", ejtése "óverfló", tehát az ó-hoz "val" társul.
Egyszer már átírtad a nyitó postot. A csonka kód helyett kaptunk egy teljeset, miközben az algoritmus is szép csöndben módosult, tehát más logikáról kérdezed hogy miért hibás. Erről az aprócska körülményről persze elfelejtettél szót ejteni.
Most meg újra átírtad a postot, javítottál pár helyesírási hibát. Amit kommentálhattál volna úgy is, hogy "köszönöm a jelzést, javítottam". De nem, Te úgy kommentálod hogy "helyesen írtam". És még le is írod a vonatkozó szabályokat ami alapján így helyes. Hadd lássa csak az utókor, hogy milyen jól ismered a szabályokat és milyen helyesen alkalmazod azokat, a többiek a hülyék, nem igaz!?
Az a sofőr jut Rólad eszembe, akinek egyszer szóltam éjszaka hogy kapcsolja fel a világítást, odanyúlt a gombhoz, felkapcsolta, majd "kösz hogy szóltál" helyett azt válaszolta nekem hogy "fel volt kapcsolva". Várjunk csak, lehet hogy Te voltál az??
Ha nem értenéd: nem a helyesírás a fő gond, hanem a hozzáállás. A tényleges szakmai résszel kapcsolatban is. Ahol már rég többször is megkaptad a választ, de még mindig nem vagy elégedett, és még mindig mindenki más a hülye aki segíteni próbál Neked.
(Amúgy, ha a nyelvtan alapvető logikája megvan, akkor az általad eddig az eredeti postban és kommentekben összesen 5 alkalommal leírt "0-át" formát is kérlek gondold végig újra! Ha megvagy, akkor következő, sokkal nehezebb feladatként jöhetne esetleg a hozzáállás, stílus újbóli végiggondolása...)
off
Azzal, hogy valaki segítséget kér, eleve elismeri, hogy hibázott, valamit félreértett, rosszul csinált. Ezzel semmi baj, de illene félretolnia a hatalmas egóját, jó volna valamiféle szakmai alázatot tanúsítani. Van az úgy, hogy nagyon rábandzsulunk a problémára, nem látjuk a fától az erdőt, hátra kellene lépni egyet, hogy szélesebb aspektusból lássuk a problémát. Aki nincs benne, az tiszta fejjel könnyebben megláthatja.
Nem értem, egyeseknek miért annyira nehéz elismerni, hogy tévedtek, hibáztak. Teljesen természetes ez. Semmi baj, megkeressük a hibát, kijavítjuk. Ez egy ilyen szakma.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
pipe-pal*
Tudjunk már magyarul!
Érdemi reakció esetleg?
man 3 system
+1. Szerintem is logikusabb lenne hogyha egy olyan magasszintu hivas mint a system() az a hivott processz exit status-aval terne vissza alapbol. De sajna nem ez a helyzet:
Az exitstatus az a [15:8] (¿vagy [14:8]?) bitekben van latszolag. A WEXITSTATUS() makro ezt banyassza ki hordozhato modon.
Ez jó, csak épp semmivel sem visz közelebb a megoldáshoz. Egyrészről az eredeti helyén a kód másként fut, ott a waitpid() -1-et ad mindig vissza és nem 0-át, másrészről ott nem is system() hívás szerepel eredetileg, hanem execlp() (szóval a hívott visszatérési értéke direktben a gyerek visszatérési értéke).
A system() hívásra már csak kínomban írtam át a sokadik próbálkozásnál, hogy ki tudjam iratni a visszatérési értéket a kimenetre a gyerekben. Egyébként amit át szeretnék írni, az konkértan ez a hevenyészett megoldás, jelenleg akkor áll le a szülőben a ciklus, amikor már nem tud olvasni a pipe-ból, de ez nagyon nem az igazi, azért akarom lecserélni (és olyanra, ami bufferelten olvas, nem bájtosával, mint most).
És hogy miért is kell, mert a libavcodec használhatatlan, az API-ja egy vicc, még a saját tooljaival sem lehet warning nélkül lefordítani. Ha menne, eszembe se jutott volna ffmpeg-et indítani és pipe-ból olvasni, hogy hol tart.
Nahát-nahát. Akárhányszor megoldjuk a problémádat, kiderül, hogy nem is azt a kódot kell javítani. És még neked áll feljebb.
Szerintem a folytatás előtt tanulmányozd ezeket: https://en.wikipedia.org/wiki/XY_problem https://en.wikipedia.org/wiki/Minimal_reproducible_example
don't waste your time on selfish idiots like bzt... I regret every moment from my life...
Ezt azért vicces így tőled látni, aztán csak odaesz a fene az összes olyan témába!
neked sem erősséged a logika ;)
// Happy debugging, suckers
#define true (rand() > 10)
Ha így is van, én tudok a magas lóról leszállva is válaszolni. Ellenben veled!
Ti egyszer, vagy akár többször is összefeszültetek. Ennek az lett a következménye, ha egy témában meglátod a másik nevét már eleve kioktató stílusban válaszolsz neki, ha segítség, ha nem, az amit írsz. Ezzel is tovább szítod a tüzet, majd megy az egymásra mutogatás, hogy ő ütött először! Ezzel jól megmutattad, hogy te sem vagy különb!
És ez most konkrétan nem csak erre a témára vonatkozik. Egyre általánosabb az oldalon!
OFF: Sajnos ezzel egyet kell értsek. Ők jönnek mindig az én topikjaimba és kezdik el a trollkodást, aztán meg rinyálnak, hogy csúnyán viszont lettek trollkodva.
Érdekes, egy másik topikomba is írt olyan, akivel volt már flamewarom, de mivel normálisan szólt hozzá ahhoz a topikhoz, én is normálisan válaszoltam neki. Nahát, hogy mik vannak!
erre csak egy lock
// Happy debugging, suckers
#define true (rand() > 10)
Ez nem az oldalon, hanem egyre általánosabb bzt irányába. Bár megpróbálsz általánosítani, de közben ismét bzt volt az első aki trágár stílusban lehazugozott valakit, miközben az egyértelműen segítő szándékkal fordult az egészhez (ha a példa kódokat kihagyod, a bzt kirohanásig az összes hsz kivonata ennyi volt: "s az output, ott van az exit code:" / "megy az pipe-pal is:")
"majd megy az egymásra mutogatás, hogy ő ütött először!"
Szerencsére 2024 van és bár a nyitót már párszor meghamisította bzt, az alatta lévő hozzászólások időponttal, időrendben szerepelnek. Szóval megpróbálhatod relativizálni a tényeket, de felesleges: ismét bzt volt az első aki páros lábbal repült bele másokba
Az pedig, hogy miután ez megtörténik, jövök popcornozni és kiröhögöm azt aki ezt a szerencsétlent védelmezi, az megint más, ezt a részét vállalom :)
// Happy debugging, suckers
#define true (rand() > 10)
https://hup.hu/comment/3141745#comment-3141745
Akárki meglássa. És igen, nyíltan hazugnak nevezlek. Most is hazudsz.
Nem tartom kizártnak, hogy mcsiv és micsa valójában egy és ugyanaz a troll. Túl gyakran válaszolgatnak egymás helyett, szerintem a mostani válaszában is összekeverte a loginokat.
Legalábbis nyilvánvalóan micsának szántad ezt a mondatod, de valójában mcsivnek válaszoltál.
bár lehet egyszerűbb lenne ebben a tudatban élned, de hidd el, egyszerre többen is lenézhetik a másikat, ez nem korlátozódik kizárólag egy személyre
// Happy debugging, suckers
#define true (rand() > 10)
Hazugság. Pontosan leírtam az eredeti topiknyitóban, be is másoltam a kódot, csak TI KÉRTÉTEK, hogy tegyem át egy önállóan fordítható forrásba.
Ezen kívül mi az, hogy "akárhányszor"???? Idejét sem tudom, mikor kérdeztem a HUP-on programozással kapcsolatban.
Pontosan! Te még egész biztos soha nem oldottad meg egyetlen egy problémámat sem, úgyhogy jogosan áll feljebb. Q.E.D. Csak fennhéjazol itt, de valójában nincs is mire.
> csak TI KÉRTÉTEK, hogy tegyem át egy önállóan fordítható forrásba.
Ebből a kommentedből is látszik, hogy nem olvastad el a két linkelt wikipedia oldalt.
> Idejét sem tudom, mikor kérdeztem a HUP-on programozással kapcsolatban.
Arra gondoltam, hogy ebben a topicban már legalább 3. verziónál tart a kérdés. Legelőször az volt a gond, hogy a waitpid -1 státust ad vissza, ami logikai hibára utal, utána 32512-t adott vissza, azt is megmagyaráztuk, most meg már azt írod, hogy de nem is az a probléma. Most így akkor ki tudná kitalálni?
Én tényleg segíteni akartam, és nem trollkodni, de ilyen mozgó célpont és hozzáállás esetén reménytelen a téma.
popen() + setvbuf(_IONBF) esetleg?
> popen() + setvbuf(_IONBF) esetleg?
Utóbbit a hívandó programba kéne behegeszteni, márpedig ahhoz az ember általában nem szeretne hozzányúlni. Ez esetben használhatjuk a kényelmesebb stdbuf parancsot (amely LD_PRELOAD mágiával fészkeli be magát az indítandó programba, hogy ott végrehajtsa induláskor a setvbuf() hívást).
Azt én simán feltételeztem, hogy a gyerekprocessz nem pufferelve ír a pipe-ba (ha ez nincs így, akkor persze a gyerekprocesszt is módosítani kellene).
A setvbuf-ot azért mondtam, mert:
Erre gondoltam:
https://pubs.opengroup.org/onlinepubs/9799919799/functions/V2_chap02.ht…
De sajnos, line bufferelt az ffmpeg kimenete.
A történet másik oldalára gondoltunk, innen a félreértés.
Te az olvasó oldalát nézed, itt valóban segíthet a szülő processzben egy setvbuf().
Én az író oldalra (ffmpeg) gondoltam, ahol ha az pufferel (mármint: ha a stdio függvényeket használja amik pufferelnek), akkor a stdbuf program tud beleinjektálni egy megfelelő helyen meghívandó setvbuf()-ot hogy mégse puffereljen.
Én se értem, hogy most mit akarsz csinálni. Minek egy C programba meghívott külső folyamatok közé egyáltalán pipe? Shell scriptben megérteném, de te nem azt írsz. Az egész egy kotyvaléknak tűnik, írd le rendesen, hogy mi ez a projekt, mit akarsz megoldani, miket indítanál, miért kell pipe.
“The world runs on Excel spreadsheets.” (Dylan Beattie)
Leírtam: "ffmpeg-et indítani és pipe-ból olvasni, hogy hol tart" Ki kell rajzolni egy progresszbárt, és ehhez olvassa az ffmpeg kimentét.
Mondom hevenyészett. Mondom épp újraírom.
Már leírtam, de idemásolom mégegyszer: "ffmpeg-et indítani és pipe-ból olvasni, hogy hol tart"
TL;DR mostanra megjavult? Ha nem, kérlek tedd ki a github-ra, úgy van esélye, hogy ránézzek.
Nem github, másik githost, de kint van, linkeltem is már. Ez az eredeti sebtében összedobott gány kód, amit épp átírok rendesre. Itt van. Ehhez kellene, hogy lekérdezzem a waitpid() értékét, de muszáj WNOHANG opcióval hívni, mert közben olvasni kell a kimenetét.
Nem ragaszkodom a topiknyitóban vázolt megoldáshoz, a lényeg annyi, hogy adja vissza a visszatérési értéket (innen tudja, mikor végzett a gyerek vagy hogy egyáltalán sikerült-e elindítani), és közben tudja olvasni is a kimenetét, hogy lássa, hol tart. Bármilyen hordozható, csak libc-t használó megoldás erre megfelel.
Kezelni kellene a SIGCHLD -t, akkor pontosan tudnád, hogy volt-e egyáltalán gyerek kilépés. Amíg nem volt, hiába hívogatod a waitpid() -t.
Hát, a man page nagyon nem ezt mondja.
Én pontosan ezt szeretném pollozni, amíg a waitpid() 0-át ad vissza és nem a gyerek pid-jét, addig olvasom a pipe-ot. Ez remekül működik is, a probléma ott van, hogy amikor a waitpid() nem 0-ával hanem a gyerek pid-jével tér vissza, akkor nem állítja a status paramétert a visszatérési értékre, és nem tudom, miért nem. Akármivel lép is ki a gyerek, a waitpid() mindig -1-et rak a status változóba.
(ps: egyébként meg az a tapasztalatom, hogy amit írsz, sosem működne. Ha azután akarnád hívni a waitpid()-et WNOHANG nélkül, hogy a gyerek már kilépett, akkor a waitpid() örökre blokkolódik, mert nem lesz státuszváltozás.)
> Ha azután akarnád hívni a waitpid()-et WNOHANG nélkül, hogy a gyerek már kilépett, akkor a waitpid() örökre blokkolódik, mert nem lesz státuszváltozás.
Nem.
Gondolkozzunk visszafelé. Ha ez így lenne, akkor soha, de soha nem lehetne biztonságosan meghívni WNOHANG nélkül, mert bármikor előfordulhatna, ugyebár multitasking oprendszerről lévén szó, hogy pont a waitpid() hívás előtt lép ki a gyerek, örökre blokkolódva ahogy írod. Tehát a fejlesztők, akik bocsánat de sokkal-sokkal jobban értenek hozzá mint Te, nem adnának ilyen lehetőséget, egyszerűen a WNOHANG lenne az egyetlen elérhető viselkedés. Amivel persze az lenne az egetrengető probléma, hogy nem tudnál várni a gyerekre, max busy loop-ban; mellesleg nyilván nem szerepelne a wait szó a függvény nevében ha mindent tudna csak várni nem.
Na de inkább nézzük előrefelé a dolgokat. Erről szól a zombi processz. Amikor egy processz kilép, de a szülője még él és virul és még nem waitpid()-elt rá, addig a rendszer megjegyzi a kilépett processz exit kódját meg még pár apróságot vele kapcsolatban, és a következő waidpid() alkalmával ezeket azonnal jelenti a szülőnek, ilyenkor tűnik el a zombi. (Kivéve ha SIG_IGN-ra rakod a SIGCHLD-ot... nem célom minden részletet egész pontosan kifejteni.)
De.
Dehogynem, pont emiatt van a zombi, még te magad is írtad. Na de egy zombi processz nem fut és nem is vált státuszt. (És egy csúnya gányolás, hogy ne fagyjon ki a waitpid(), teszem hozzá.)
Citation needed. Amit a Linux forráskódjában látok, nem ezt támasztja alá. Maradjunk annyiban, nem alaptalanul szokott kiborulni Linus.
Eggyel korábban azt írtad, hogy kifagyna a waitpid. Válaszoltam hogy nem fagyna ki, mert erre van a zombi. Most meg azt írod, hogy nem fagyna ki, mert a zombi "gányolás" pont ezért van.
De jó is hogy pontosan tudod hogy miről beszélsz, következetesen. Legeslegalább a harmadik alkalom ebben a topikban, amikor megváltozik a történeted, véleményed, úgy hogy hirtelen mindig is ezen az új verzión voltál.
De persze aki bedobja hogy a zombi a kulcsszó, annak persze nem volt igaza, annak ellent kell hogy mondj.
Mily szerencse, hogy a korábbi hozzászólásokat nem lehet szerkeszteni. Rajtad kívül mindenki látja hogy mi a szitu.
(Mellesleg elmesélhetnéd, hogy miért gányolásnak, és nem rendes megoldásnak tartod. Hogy szerinted a rendesen megtervezett megoldás mi lett volna.)
> Citation needed.
Harmadik napja, sokak segítségével nem bírsz kijavítani egy kábé tíz soros kódrészletet. Miről is beszélünk?
> Amit a Linux forráskódjában látok, nem ezt támasztja alá.
A waitpid() régebbi mint a Linux.
> Maradjunk annyiban, nem alaptalanul szokott kiborulni Linus.
A Te buksidat nyilván megsimogatná.
Iszonyat nagy a szád, pedig nem mintha te megoldással szolgáltál volna... Úgyanúgy fogalmad sincs, mint a többieknek.
Miről is beszélünk?
És ez hogy jön ide, és kit érdekel? Nekem Linux alatt nem mükődik úgy, ahogy a man mondja.
> És ez hogy jön ide, és kit érdekel? Nekem Linux alatt nem mükődik úgy, ahogy a man mondja.
És 100%-ig biztos vagy benne, hogy a hiba a Linuxban van, nem benned. Ez a baj.
És 100%-ig biztos vagy benne, hogy megengedhetsz ilyen hangot velem szemben, miközben még semmit nem tettél le az asztalra? Na EZ AZ IGAZI BAJ.
Nem gondolom, hogy a Linuxban lenne a hiba, soha nem is mondtam ilyesmit, ez csupán csak a Te beteg fejedben létezik. Amit valójában írtam, ideidézem, bár rajtad kívül úgyis mindenki más látja: "nem állítja a status paramétert a visszatérési értékre, és nem tudom, miért nem." Húzd alá azt a részt, ahol állítólag a Linux-ot hibáztatom ebben, Mr. Nagypofájú!
Na ugye, hogy csak beképzelted az egészet! Csak engem próbálsz hibáztatni, miközben megoldást, na azt még nem láttunk tőled (sem)!
Az első posztomra válaszul lehurrogtál, kioktattál. Mégis mit vársz?
Hogy nagy a szám? Például abban a kommentben átfogó képet adtam a történetről, nemtriviális buktatókról, és érdekességként meséltem kicsit egy olyan szituációról, ahol ennél sokkal bonyolultabb környezetben sikerült megoldanom a problémát. Nem fórumon kérdezgetni napokig amíg szerencsétlenkedem vele, hanem leülni és egyedül megoldani. Mások erre megköszönték volna hogy mesélek egy kis érdekességet, meg persze a konkrét szituval kapcsolatban is érdemleges adalékot nyújtok (nem, bocs, nem konyhakész megoldást). Szerinted meg -- kapásból arra a kommentre válaszolva -- fingom sincs az egészről és csak az arcom nagy. Hát, messze nem akkora mint a tiéd, a tudáshoz mérve meg pláne nem!
Megoldást meg nem azért nem adok mert nem tudok, hanem azért mert nem vagyok hajlandó olyannak aki ilyen stílusban kommunikál mint Te! Ennyike. Már így is sokkal több segítséget kaptál, mint amennyit megérdemeltél volna.
(Amúgy... biztos csak én maradtam le róla... hol is van az aktualizált MRE amiben minden eddig említett hibát kijavítottál és még mindig nem működik??)
Mindjárt az első posztoddal csak zajt generáltál, mindenféle megoldási javaslat nélkül. Mégis mit vársz? Tudom, hogy a pipe EOF és a gyerek kilépés nem ugyanaz, pont ezért akarom átírni az egészet, az nem segítség, ha a nyilvánvalót szajkózod kioktató stílusban.
"Mily szerencse, hogy a korábbi hozzászólásokat nem lehet szerkeszteni. Rajtad kívül mindenki látja hogy mi a szitu."
Nem látok bele a fejedbe. Nem tudhatom, mi az, ami számodra triviális és fölöslegesen írom le (bár más fórumozónak akkor is hasznos lehet), és mi az amivel nehézségeid támadhatnak. Ha valamit fölöslegesen írok le, akkor azt attól függetlenül megköszönheted, vagy figyelmen kívül hagyhatod, de ha azt olvasod ki belőle hogy az illető felvág a tudásával akkor ott szerintem bajok vannak.
Megmutattam, hogy többféle lehetséges viselkedés is van, attól függően, hogy elfogadható-e az adatvesztés (amit roppant valószínűtlennek tartottaml volna, de persze a kontextust nem írtad le így nem tudhattam), elfogadható-e ha unoka processz esetén azt is meg kell várnunk, stb. Kértem pontos specifikációt hogy mit is szeretnél csinálni, hiszen a megoldás mikéntje ezen múlhat.
Erre explicit válasz nem érkezett, csak sokkal-sokkal később a másvalakinek adott válaszodból derült ki, hogy valamifajta progress bar szerűség érdekel, tehát ha a gyerek kilépett, akkor baromira nem érdekel az esetleg bennragadó feldolgozatlan adat. Ezt mondjuk megírhattad volna válaszként amikor kértem a megoldandó probléma specifikációját. Mert ha más a cél (például az összes kimenetet be kell olvasni) akkor azt másképp kell csinálni. Azt meg gondolom végképp nem várod hogy az összes lehetséges értelmezésre előálljon valaki egy kész, bevizsgált, leellenőrzött megoldással. De nem, nem a feladat specifikációját kaptam, hanem egy olyan választ, amilyet, amelyik minden egyes szavamba nekiállt belekötni. A folytatást ehhez igazítottam.
Mármint ezt én mondom neked, úgy értetted.
Miért kéne megköszönnöm azt, hogy amit írkáltál, annak a problémához és konkrét kérdésemhez SEMMI köze nem volt, ráadásul mindezt kioktató hangnemben tetted, miközben SEMMIFÉLE megoldási javaslattal nem is álltál elő benne. Ha legalább tippeket is írtál volna bele, úgy mindjárt más lenne a leányzó fekvése, de nem tetted, csak kioktatni akartál, miközben nem vagy abban a helyzetben, hogy ezt megtehesd.
De hogy értsd, konkrét példák a posztodból (csak pár, nem az összes hibád):
- "Az, hogy a gyerek processz kilép, és az, hogy a pipe-on EOF-ot kapsz, az két teljesen független esemény" - úgy írod ezt, mintha a mintaprograrom összekeverné e kettő eseményt, holott nem is. Hibásan feltételeztél valamit, és ki akartál oktatni róla, pedig csak te nem tudtad elolvasni a C kódot.
- "az eredeti gyerek kiléphet, a pipe még él és virul és bonyolíthat további forgalmat, miközben a waitpid() már jelenti hogy kilépett." - komplett hülyeség, ez csakis abban az egy speciális esetben fordulhat elő, ha a gyerek démonizálja magát, aminek megint, semmi köze a témához.
- "A programod amúgy mindkét sorrendet hibásan kezeli. Koncepcionálisan nem gondoltad végig hogy mit akarsz csinálni." - megint hülyeségeket írsz, miféle "mindkét sorrend", és kiotató hangnemben feltételezted, hogy én nem gondoltam végig, holott te nem tudtad csak elolvasni a C kódot. És elárulom, semmi baj a sorrenddel (és két függvény között eleve nincs és nem is lehet "mindkét sorrend", csak egyféle sorrend, a két eset kölcsönösen kizárja egymást).
- "Sajnos egyébként nincs igazán jó általános válasz." - mondd csak, ezt tán' segítségnek szántad? Egyébként tévedtél ebben is, már megvan a jó válasz, nagyon is létezik.
...stb. stb. stb.
Szóval igen, aki ilyen paraszt stílusban irogat hülyeségeket, úgy próbál kioktatni, hogy még elolvasni sem tudta a C kódot, az biza' ne számítson tőlem másra, mint viszonttrollkodásra, de ezt már milliószor leszögeztem, nincs min csodálkozni.
> Ha legalább tippeket is írtál volna bele
Miért álljak neki tippeket írni, amíg nem tudom hogy mi a cél? Megkérdeztem hogy mi az elvárandó viselkedés egyes speciális esetekben. Erre nem jött válasz. Nem ez volna az első lépés a megoldás felé: tisztázni hogy pontosan mit is akarunk??
> úgy írod ezt, mintha a mintaprograrom összekeverné e kettő eseményt, holott nem is. Hibásan feltételeztél valamit, és ki akartál oktatni róla, pedig csak te nem tudtad elolvasni a C kódot.
Feltételezed hogy mindenki pontosan belelát a fejedbe és mindenki pontosan tudja hogy mi az ami számodra evidens és mi az ami esetleg problémás. Nem kioktattalak, hanem leírtam, mint egy lehetséges fontos információ, amely fölött talán lehetséges hogy esetleg átsiklottál.
> komplett hülyeség, ez csakis abban az egy speciális esetben fordulhat elő, ha a gyerek démonizálja magát, aminek megint, semmi köze a témához.
Tehát nem komplett hülyeség, mivel -- az általad felfedett rész információk alapján -- lehetséges hogy így lett volna. Erre az kéne hogy legyen a válasz, hogy leírod hogy nem így van, nincs ilyen a játékban, nem kell vele törődni.
> megint hülyeségeket írsz, miféle "mindkét sorrend"
Amíg egy ciklusban felváltva olvasol adatot és nézel rá hogy él-e a gyerek, mint ahogy tetted, igenis lehetséges az is, hogy a bemeneten kapsz először EOF-ot, de lehetséges az is, hogy a gyerek kilépéséről értesülsz először. A kódnak mindkét esetet helyesen kell kezelnie.
Az eredeti kódod, a break utasítással, amely talán nem is maradt fenn az utókornak, egyértelműen hibás volt itt.
Abban igazad van, hogy ez nem az a hiba, amelyiket te kerested, ez egy másik hiba. De miért kell leugatni aki talál egy hibát, jóllehet nem azt amelyiket te kerested?
Kiegészítettem az általad mutatott csonka kódot, ki tudja hogy mennyire másképp mint ahogy Te tetted, lefuttattam, más eredményt kaptam. Találtam egy hibát, amely esetleg megmagyarázhatta az eltérő viselkedést, rámutattam. Lehet rá reagálni úgy is, hogy hülye vagy, nem is olvastad el a kódot (aha persze), nem erre vagyok kíváncsi, elképesztő hogy hogy nem képes az a kommentelő csóka rögtön azt megtalálni amit keresek, csak digitális szemetet generál. Vagy úgy is, hogy köszi, javítom, egy lépéssel közelebb kerültünk a megoldáshoz, lássuk mi a következő lépés.
> Sajnos egyébként nincs igazán jó általános válasz." [...] Egyébként tévedtél ebben is, már megvan a jó válasz, nagyon is létezik.
Átsiklottál az "általános" szó fölött, meg a szövegkörnyezet fölött. Az általam felvázolt teljesen általános esetre nincs jó válasz, leírtam hogy miért, és leírtam hogy egy adott szituációban mi volt a legjobb workaround amit találtunk. A Te konkrét szituációdban könnyen lehet hogy volt jó válasz, csak ehhez ismernünk kellett volna a konkrét szituációt, konkrét elvárt viselkedést, amit miután rákérdeztem se írtál le.
Ha valaki nem konkrét megoldás javaslattal áll elő első körben, hanem mesél a történetről (ami mese talán újdonság neked, talán nem, senki sem tudhatja), majd feltesz egy igenis releváns kérdést amelyre adott választól függhet a folytatás, akkor ez tényleg kioktató, használhatatlan digitális hulladék?? Hát jó, örülök hogy ma is tanultam valami újat. Köszönöm a leckét!
Beismerő vallomás, hogy trollkodtál csak. Tehát jogos volt a viszonttrollkodásom, köszönöm!
...az általad felvázolt általános esetnek semmi köze nem volt a konkrét kérdésemhez.
Felhívnám a figyelmedet arra, hogy SEMMIFÉLE megoldási javaslattal nem rukkoltál elő, így nem tartozom neked semmivel, és nem vagy abban a helyzetben, hogy bármit is számonkérhess.
Maradj csak meg abban a tudatban, hogy "nem is létezik jó válasz". Részemről ennyi.
> Beismerő vallomás, hogy trollkodtál csak.
Hát, ha a trollkodás szó azt jelenti hogy valaki visszakérdez hogy tisztázza pontosan mi is a megoldandó feladat... eddig azt hittem, ez a szó mást jelent... de az új jelentése szerint ez esetben valóban trollkokdtam.
> az általad felvázolt általános esetnek semmi köze nem volt a konkrét kérdésemhez.
Amit akár tudhattam is volna, ha leírod pontosan hogy mi az elvárás, vagy sikerül kiolvasnom a gondolataidat. Sajnos az első nem ment neked, a második pedig nem ment nekem. Így nem tudhattam, van-e köze hozzá vagy nincs. Gondoltam, nem lehet belőle baj ha megemlítem. Hát, tévedtem.
> nem tartozom neked semmivel, és nem vagy abban a helyzetben, hogy bármit is számonkérhess
Nem is állítottam ezek egyikét sem.
> Maradj csak meg abban a tudatban, hogy "nem is létezik jó válasz".
Arra a problémára, hogy a gyereket várjuk meg, a gyerek által kiírt összes adatot olvassuk végig, de ennél érezhetően több késlekedés már ne legyen, az esetleges unokát már ne várjuk meg (ami, nem tudhattam, akár lehetett is volna itt a feladat, kérésem ellenére nem tisztáztad), nem tudok igazán tökéletes, elegáns megoldást; csak picit gányolós és gyakorlatban nagyon jót. Amelyik progiban ez az igény felvetődött, ott a többi fejlesztő illetve beszélgetésben résztvevő sem tudott. A luit fejlesztői sem tudtak. Érdekességként, van kedved megmutatni esetleg?
A Te igényeidre, melyeket kérésem ellenére nem tisztáztál, csak később egy másik szálban (nevezetesen hogy oké ha a gyerek kimenetének a vége elvész), soha nem állítottam hogy ne létezne jó válasz.
Nocsak, kiderül, hogy csak nem tudsz olvasni. Nem meglepő. Minden kérdésedre volt már válasz, hogy nem értetted, az a te bajod.
> Kezelni kellene a SIGCHLD -t
Egyáltalán nem muszáj kezelni, teljesen jó ha a szignál része nem érdekel, csak waitpid() hívásokkal nézel rá hogy él-e még, vagy várod meg. A szignálkezelés sokkal bonyolultabb, mint a waitpid(), csak akkor érdemes elindulni abba az irányba ha nagyon muszáj.
Ha egy olvasás sikerül, de a kapott hossz nulla, az az EOF. Pipe-pal dolgozva ez azt jelenti, hogy az (utolsó) író program lezárta a pipe-ot (vagy befejeződött).
Off: az ffmpeg hívja az editor-t részt nem tudom követni, de természetesen úgy értettem, hogy a mcve-t tedd közzé. [Off: hibát a stderr-re írunk, nem a stdout-ra, de ha mégis, akkor szorgalmasan fflush-oljunk.
Én is ebből a feltevésből indultam ki, de sajnos nem helyes. A forrás egy külsős vinyón található, és idő, amíg felpörög, ilyenkor előfordulhat, hogy kétszer is flush-ol az ffmpeg a kimenetre, emiatt üreset olvasok, és a ciklus kilép, holott még fut az ffmpeg. Nagyon ritka jelenség, de sajnos előfordult már. Emiatt (is) akarom átírni, mert ez így nem megbízható.
Nem csodálom, mert ilyen rész nincs is.
Az editor hívja az ffmpeg-et a gyerekben, majd a szülő olvassa a kimenetét és az alapján időnként meghívja az ui_progressbar()-t. Ehhez két sor kell a kimenetből: "Duration", a teljes videó hossza, illetve a "frame=" sorokból a "time", hogy épp hol tart ebből a konvertálás.
Nincs ám mindenhol stderr. Nevezetesen Win GUI alatt csak az stdout-ot nyitom újra, amit a dynamic linker bezárt, mikor látta a PE fejlécben, hogy GUI alkalmazás. Persze berakhatnám ugyanezt az stderr-ba is, de akkor is ugyanoda menne.
Tényleg sok minden kavarog itt, inkább megvárom a publikus [mcve]-t.
Mi kavarog? Pipe EOF-ot néztem eddig, de az nem jó, ezért át akarom írni gyerek pid figyelésre. Nem kavarog itt semmi, faék minden.
Ja, hogy maga a projekt egy nagyobb multiplatformos cucc? Hát ez van.
Jó lenne, ha jól csinálnád. Az utolsó író-processz kilépésekor jön a read=0, tehát ha szülő-oldalon nem zárod le a write-handle-t, akkor nem jön EOF.
ÁÁÁÁ, megvan! Rájöttem, miért van az, hogy az eredeti helyén a waitpid() mindig -1-et tesz a status-ba. Nagyon nem triviális.
Aki ténylegesen megpróbált segíteni, azoknak hálásan köszönöm, a többiek meg szégyelljék magukat, amiért digitális szemetet generáltak.
(ps: a megoldás a főprogram által dinamikusan linkelt függvénykönyvár által futásidőben linkelt függvénykönyvtárak által nyitva hagyott fájldeszkriptorok környékén keresendő.)
Vigyázz, nehogy véletlenül eláruld nekünk, mi volt pontosan a probléma, még felrobbanna a hup! :-)
Amúgy a minimal reproducible example-ben én is a futási időben betöltött függvénykönyvtár által nyitva hagyott fd-re gyanakodtam, nagyon gyanús volt benne az a kódrészlet, és nyilván mi más is állhat a waitpid() fura működésének hátterében mint egy irreleváns fájlleíró?! :-)
(De most tényleg, komolyan, ennyi flame után azt akarod velünk elhitetni hogy a hibát egy olyan dolog okozta ami az általad mutatott MRE-ben benne se volt? És hogy az MRE miért volt hibás, arra rájöttél már, vagy most már nem érdekel?)
Mondom én, csak digitális zajkeltésre vagy képes. Felhívnám a figyelmedet arra, hogy SEMMIFÉLE megoldási javaslattal nem rukkoltál elő.
Pedig igaza van, én még mindig nem értem, hogy mi volt a probléma, ködösítesz, mint az állat. Ha most statikusan linkeled a binárist, akkor jó értékkel tér vissza?
“The world runs on Excel spreadsheets.” (Dylan Beattie)
> a hibát egy olyan dolog okozta ami az általad mutatott MRE-ben benne se volt
+++
Továbbra is azt állítod, hogy a -1 status mellett semmi egyéb jelenség (signal, errno, waitpid által visszatérési értéke, stb.) nincs?
Azt.
A -1-et egyértelműen az okozta, hogy nem volt a gyerekben minden fájldeszkriptor lezárva. Amint a gyereket azzal kezdtem, hogy az összes dinamikusan linkelt függvénykönyvtár destruktorát hívja meg még az exevlp() előtt, beleértve a futásidőben linkelt függvénykönyvtárakat is (dlclose), azután a waitpid() a szülőben elkezdett a man page-ben leírtaknak megfelelően működni.
Problem solved.
:D
// Happy debugging, suckers
#define true (rand() > 10)
na szóval... ahol meghívódik az _exit(), ott a processznek vége... utána már semmiféle destruktor nem hívódik...
szóval: akkor mi a magyarázat?
szerk: azt ne mondd, hogy amikor a kernel zárja le a file deszkriptorokat, akkor megváltoztatja az exit kódot
a waitpid wait4-et hív, ami egy syscall... userspace-ben nincs ott semmiféle logika...
szóval: valami meggyőzőbbet mesélj nekünk...
(Nemide.)
Ja, én voltam a hülye, amiért feltételeztem, hogy a HUP-os trollcsordától érdemes bármilyen szakmait is kérdezni. Többet nem fogok.
persze, mert a hup trollcsorda volt a hülye, hogy a sehol nem említett dolog volt a probléma okozója és ezt nem találták ki :D (de azért szépen kikupálták a maradék 3 problémát amit még így is sikerült megtalálniuk)
// Happy debugging, suckers
#define true (rand() > 10)
valamivel meg kell védje
magátaz egojátDe igen, megírtam, hogy miért nem jött EOF a pipe-ról, amikor kilépett a gyerek: mert volt még író folyamat: maga a szülő is nyitva tartotta a pipe-ot írásra.
Csakhogy sosem volt probléma, hogy ne jött volna EOF; a gond épp az volt, hogy két fflush között üreset olvasott, így EOF-nak hitte, ami nem is volt EOF.
Nem, ez nem így működik, a szülő pipe végét és a gyerek pipe végét egymástól teljesen függetlenül kell lezárni, és a szülő oldali fele eleve nem is írható. Az, hogy a szülő oldali fele még nyitva van, amikor a gyerek oldali fele már le lett zárva, teljesen normális, és ilyenkor már nem is lehet olvasni belőle, hiába van a szülő oldali fele még nyitva.
ezt a baromságot: már hogy a túróban ne lenne írható mindkét processzben? mindegy, hogy melyik felől írod bele a pipe-ba, mindkettőt visszaolvashatod
de ennek mi köze van az exit kódhoz?
> így EOF-nak hitte, ami nem is volt EOF
Most akkor az derült ki, hogy nemcsak a waitpid() a hibás, hanem a mittomménmelyik olvasó függvény is amelyik EOF-ot ad vissza amikor nincs is EOF? Egyre izgibb!!
Ahelyett, hogy további zajt generálsz, próbálj meg megtanulni OLVASNI.
Eleve azért kezdtem a waitpid()-es újraírásba, mert a read()-es megoldásról tudtam, hogy nem százas. Ha ezt nem érted, az a te bajod.
Ad1: ehhez masszív bénázás kellett történjen a felhasználói programban.
Ad2: egy pipe(2) két handle-t ad vissza, ha fork-olsz, akkor négy lesz belőle, ezért oldalanként le kell csukni egyet-egyet, marad kettő.
Nálam akkor jött elő, amikor az ffmpeg hosszan IO blokkolódott, egyébként nem. De az már elég az újraíráshoz, hogy volt eset, amikor előfordult.
Nem változtat a tényen, hogy a pipe egyirányú, a visszaadott fd párból az egyik csakis írható, a másik csakis olvasható. man pipe
"unidirectional" = egyirányú, "read end" = a csak olvasható vége, "write end" = a csak írható vége.
Ad1: timeout-ot vagy más hibát vettél üres inputnak.
Ad1: ez is igaz, de nem erről volt szó, hanem arról, hogy a fork után mindkét oldalon le kell zárni azt a handle-t, amit nem akarunk használni; ha mondjuk egy gyerek->szülő irányú pipe, akkor a szülő lezárja a write-handle-t, a gyerek még a read-handle-t.
Nincs itt hiba. A pipe olvasás read() blokkolódása feloldódhat úgy is, hogy közben nincs mit olvasni (tipikusan ha a gyerek két fflush között nem ír semmit). Ez teljesen normális, bár nem szokott előfordulni, ritka, de lehet.
Le kell. Hol itt a kérdés? Ja, hogy a faszjancsik miatt átírt kódból véletlenül lemaradt a gyerek oldalon? Lemaradt. Az újraírt kódomban ott van, ezért nem is értettem, ahogy az eredeti topiknyitóban is ott volt. (A lecserélendő megoldásban meg direkt nincs ott, mert elcrashel tőle az ffmpeg.) De ha már szőrszálhasogatás, a pipe író végét is le kell zárni a gyerekben a dup2 után. Beraktam.
EDIT: ez érdekes. A helyi kódomban is ott van a lezárás. Sőt, ott még a "close(1)" és "close(2)" is, ami szintén "eltűnt" a topiknyitóból. Viccelődik a Drupal? No mind1, most a topiknyitó bitre az, amivel valójában teszteltem.
> A pipe olvasás read() blokkolódása feloldódhat úgy is, hogy közben nincs mit olvasni
-1 EINTR értékkel például feloldódhat, igen. Vagy nonblocking módban -1 EAGAIN értékkel.
0 értékkel a man page szerint nem ("zero indicates end file"), és az én eddigi tapasztalataim alapján sem.
Nyilván jobban tudod. Van kedved esetleg mutatni egy reprodukálható teszt esetet is hozzá? Csak hogy egészen biztosra ki tudjuk zárni azt a lehetőséget hogy esetleg Te néztél be valamit.
ez "szándékos félreértés"... egyértelműen azt mondta, hogy a pipenak a write fd-je nincs lezárva a parent-ben
még mindig várjuk a magyarázatot. mert ebből még csak annyi látszik, hogy fingod nincs, hogy mi volt a baj, tehát fingod nincs, hogy hogy működik az egész...
hol a waitpid a "hibás", hol a destruktorok, hol a read-del való bénázás... (persze, engem azért leseggfejeztél, hogy miért tettem át a pipe-ot non-blocking módba, ugye)...
LOL :-D :-D :-D :-D :-D :-D :-D :-D Azért az nem piskóta, hogy még a gyerek ágat sem vagy képes megkülönböztetni a szülő ágtól. Ennyit rólad.
seggarc vagyok, már mondtad, már unalmas... de a kérdésre még mindignem válaszoltál, még mindig nem tudjuk, hogy mi volt a probléma
te most csak szívatod, ugye? valójában nem várod hogy transzparensen leírja, ugye?
ha véletlenül mégis akkor szerintem tök hiába.
Gábriel Ákos
De pláne, mivel már leírtam, csak feljebb kéne görgetni hozzá kicsit. Egyébként micsának nem válaszolok ha megnézd, ez most kivétel volt, mert hát ezen annyira kellett röhögnöm...
Egyébként ha már így befutottál, az mcsiv és micsa trollokra miért nem szólsz rá soha? Ők bármit garázdálkodhatnak szabadon?
@gabrielakos, hol vagy ilyenkor? Micsa szánalmas ámokfutásából sugárzik az ártó szándék és rosszindulat, nincs is benne semmi más egyértelműen, és te mégsem szólsz rá. Miért nem?
nem az lenne a korrekt? :D
de igen: bzt szájából ilyet hallani, hogy bocs fiúk, tévedtem... az népmese: sosem volt és sosem lesz :)
Most lenne egy vadonatúj ötletem: ha van még hiba, akkor készíts egy [mcve]-t, és tedd fel github-ra.
Már mondtam, hogy nem githubozok és a probléma is megoldva.
Egyébként meg a régihez hasonlóan az új is fel fog kerülni egy githostingra (ami nem github), amint valamelyest használható állapotba kerül az újraírás. Jelenleg nincs értelme még kitenni, mert nagyon gyerekcipőben jár, korai fázis. Az új projekt létrehozása megy, a projekt metaadatok betöltése és mentése megy, de szprájtot, médiát még nem lehet importálni és menteni sem lehet még vele.
Ez nem vadiúj ötlet, ezt mindig így csinálom.
Ugye nem gugliztál rá arra, hogy mcve?
https://stackoverflow.com/help/minimal-reproducible-example
Természetesen, mert nálam tűzfalból tiltva van a gugli (és a fészbúk is).
És nincs szükségem keresésre, tudom, mi az az MCVE, MRE vagy épp PoC. Igen, itt az okozta a gondot, hogy a probléma egy komplex környezetben jött elő, amit hibásan redukáltam, nem reprodukálható egy egyszerű kis kóddal, hisz abból mint kiderült, hiányzik az, ami a problémát előidézte. Tisztában vagyok vele, hogy a 0 eredmény egy másik bug következménye, mint a -1. De pont azért, mert már tisztában vagyok vele, nem látom értelmét feleslegesen több energiát feccölni ebbe.
Probléma megoldva, továbbléptem. Nem izgat, ha pár HUPos trollnak még habzik a szája (nem rád gondoltam).