Üdv,
Két programom kommunikál unix domain socket segítségével. Az az érdekesség, hogy egy bizonyos idő után az egyik program SIGPIPE hibát kap az íráskor.
A különböző fórumok azt írják, ez csak akkor lehetséges, ha lezárom a socketet.
A problémám a következő: jelenleg egy fia kódsor nincs a programomban, ami lezárná...
Mi lehet az oka?
- 6009 megtekintés
Hozzászólások
Törölj ki a programodból _mindent_, ami nem szükséges a jelenség reprodukálásához, aztán kopizd be.
- A hozzászóláshoz be kell jelentkezni
Ez sajnos nem megoldható, annál összetettebb a projekt egyik fele, a másik felének a jó részéről meg nincs forráskódom (kb. plugint fejlesztek).
Azért találtam érdekességet:
http://stackoverflow.com/questions/2235938/what-can-cause-a-spontaneous…
- A hozzászóláshoz be kell jelentkezni
> egy fia kódsor nincs a programomban, ami lezárná...
Akkor csak 1 lehetőség van: az exit zárja le.
- A hozzászóláshoz be kell jelentkezni
Fut még mind a kettő, amikor ez történik.
Közben olvastam olyat (a fentebbi stackoverflow-os fórumon), hogy tud az is okozni ilyet, hogy exec történik, és nincs beállítva az FD_CLOEXEC. Mondjuk én nem exec-elek.
Viszont a másik érdekes, ami okozhatja állítólag, és ez sajnos az én esetem is, hogy az egyik oldalon nagyon gyorsan termelem az adatokat, a másikon meg lassan fogasztom. És ez is bedöntheti az egészet.
Aztán persze lehet, hogy ki fog derülni, hogy valami egyszerű dolog van mögötte. Mindenesetre most érdekes problémának tűnik.
- A hozzászóláshoz be kell jelentkezni
igen, mert queue overflow esetén ez fog történni, bár nem SIGPIPE-al kéne zárnia, ami részletkérdés.
Ami esetleg még megtörténhet (bár a nyelvet nem írtad le), de c-ben lazán meg tudod csinálni hogy felülírod valahol a socket memória területét.
Ha az előbbi a hiba, hogy overflow-olsz, akkor csak annyit tudsz tenni, hogy nyitsz egy szálat, ami folyamatosan olvassa befele az adatokat majd töltesz felfele egy puffert amiről az eredeti szálad csemegézik.
- A hozzászóláshoz be kell jelentkezni
Viszont a másik érdekes, ami okozhatja állítólag, és ez sajnos az én esetem is, hogy az egyik oldalon nagyon gyorsan termelem az adatokat, a másikon meg lassan fogasztom. És ez is bedöntheti az egészet.
Nem, olyankor csak var az irassal (hacsak az open()-nek nem adtal O_NONBLOCK flaget). SIGPIPE csakis akkor jon, ha a pipe masik vegen nem figyel senki.
- A hozzászóláshoz be kell jelentkezni
Elvileg a unix domain stateless nem? Marmint hogy nem kene varnia az irassal, hanem beirja, majd overflow-ol ha nagyon nem akar kiesni a masik oldalt.
- A hozzászóláshoz be kell jelentkezni
Nem merem biztosra mondani, de nem tartom valoszinunek. Mindjart osszedobok egy tesztprogramot, aztan meglatjuk :-)
- A hozzászóláshoz be kell jelentkezni
Elkeszult a tesztprogram, a fogado oldal egy
socket()/bind()/listen()/accept()
-bol, a kuldo oldal egy
socket()/connect()/sendfile()
-bol all, egy ~200k-s filet kuld at egyben ugy, hogy a fogado oldal csak masodpercenkent olvas egy-egy karaktert, es nincs semmi hibajelzes, szepen csordogalnak at a karakterek.
- A hozzászóláshoz be kell jelentkezni
Thx a tesztet!;) a kuldo wait-el vagy a socket bufferel?
- A hozzászóláshoz be kell jelentkezni
Nincs mit :-)
Hirtelen nem talaltam semmi leirast, de az lenne logikus, es a mukodesbol is ugy tunik, hogy a kernelben van egy queue, ahova megy az iras. Amikor az megtelik, a kuldo processz
write()
-ja blokkol, hacsak nem
O_NONBLOCK
modban nyitottad meg (akkor
EWOULDBLOCK
hibat kapsz).
Pipe-oknal (ami nagyon hasonlit a stream modu sockethez) egy 64k-s puffer van a kernelben, gondolom, itt is valami hasonlo meretu lesz.
Itt megtalalod a forrast:
- A hozzászóláshoz be kell jelentkezni
Én ugyanezt most megcsináltam unix domain socket-tel (socketpair), ott is csordogálás megy. Szóval ez zsákutcának tűnik.
- A hozzászóláshoz be kell jelentkezni
En is unix domain socket-et csinaltam, csak nem socketpair()-rel.
Mindenkeppen arrafele keresgelnek, hogy az olvaso oldal lezarja a kapcsolatot, mert SIGPIPE-ot maskepp nem kaphatsz.
- A hozzászóláshoz be kell jelentkezni
Igen, már csak a hol a kérdés :-).
Az olvasó oldal egy Verilog VPI plugin. Az érdekes az, hogy iverilog-gal futtatva rendben működik minden, ha ModelSim-et használok (6.5b), akkor körülbelül a 17000-18000-edik olvasás tájékán leáll.
Csak nagyon erős bennem az a "nevelés", hogy a hiba az én kódomban van, ritka eset, hogy más okozza.
- A hozzászóláshoz be kell jelentkezni
Igen, már csak a hol a kérdés :-)
Na igen... :-)
Az olvasó oldal egy Verilog VPI plugin
Ha jol sejtem, akkor ezt te irtad. Probalj meg letenni egy-egy breakpointot olyan helyekre, ahol "eszreveszed", hogy lezartad a kapcsolatot, hatha kiderul valami.
Csak nagyon erős bennem az a "nevelés", hogy a hiba az én kódomban van, ritka eset, hogy más okozza.
Lattunk mar sokmindent... ;-)
Biztatasul alljon itt az egyik gpsd fejleszto alairasa:
GDB has a 'break' feature; why doesn't it have 'fix' too?
;-)
- A hozzászóláshoz be kell jelentkezni
Írj egy minimális méretű kódot, ami utánozza a "gyors termelő", "lassú fogyasztó" jelenséget, és akkor kiderül.
- A hozzászóláshoz be kell jelentkezni
Hmm. Ravasz. Kipróbálom.
- A hozzászóláshoz be kell jelentkezni
Nem, valószínűleg nem ez okozza.
- A hozzászóláshoz be kell jelentkezni
Nos, nem úgy tűnik, mintha gond lenne.
- A hozzászóláshoz be kell jelentkezni
> az egyik program SIGPIPE hibát kap az íráskor.
Akkor a "másik" zárja le. Pld ha az "egyik" 0 hosszú blokkot küld, akkor a "másik" hiheti, hogy vége a kapcsolatnak, és lezárja a socket-et, amire az "egyik" SIGPIPE-ot kap.
Nincs jobb ötletem.
- A hozzászóláshoz be kell jelentkezni
Nekem sincs. Ha rájövök, mi okozza, megírom. A memóriaterület elrontását még lehetségesnek találom.
- A hozzászóláshoz be kell jelentkezni
Anno en is belefutottam ilyesmibe, a megoldas egy signal(SIGPIPE,SIG_IGN) volt a program elejen, es akkor ennyi. Persze akkor jo ez, ha egyebkent a sigpipe-ot nem akarod hasznalni aktivabban ma'sra.
A `man` szerint sigpipe akkor fordulhat csak elo ha egy (masik oldal altal) lezart fd-be irsz bele, de ez (szerintem legalabbis) race condition nelkul nem ellenorizheto". Elvileg csinalhatsz ugyan egy select(fd+1,NULL,&wset,NULL,&tvnull); szintu" ellenorizest, ahol a &wset-be beteszed azt az egy szem fd-t, a &tvnull-ba pedig a (0,0)-s ido"tartamot - es akkor ez mogmondja ugyan hogy az fd irhato-e vagy sem (mindenfele mellekhatas, blocking vagy sigpipe nelkul). De ha ezutan jon a write(fd,...,...), akkor attol me'g lehet hogy a select() es a write() _kozott_ feluton szakadt es/vagy za'rt az fd ma'sik oldala.
Ha figyelmen kivul hagyod (SIG_IGN) a sigpipe-t, akkor a write() egy -1 / errno==EPIPE kombinacioval kell visszaterjen - tehat a helyzetet alapjabanveve ugyanugy tudod kezelni. Lasd me'g: `man 2 write`, "errors" szakasz.
- A hozzászóláshoz be kell jelentkezni