Zjištění chyby při neúspěchu fwrite()

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #75 kdy: 02. 07. 2018, 22:23:51 »
Na což se neptal, nesouviselo to s tím na co se ptal, a ani to nijak nepomohlo s jeho problémem. Rada na nic.
Vy jste stále ještě nepochopil, jaký problém se tu řeší. Takže vaše názory na to, co pomohlo a co ne, jsou k ničemu.

Což udělal, a podle jeho reakcí soudě vyzkoušel. Že tvrdíš, že to nevyzkoušel, že tvrdíš, že to nenapsal, přestože to má uvedené hned v prvním příspěvku - to už je tvůj problém. A tvá drzost.
Kdyby napsal výsledky toho pokusu, napsal by fwrite() zaplnilo disk a vrátilo v poslední smyčce 0 a posix_get_last_error() také 0, v druhém pokusu vrátilo po zaplnění disku error_get_last() hodnotu NULL. To by to ovšem nejdřív musel vyzkoušet, že… Kód v prvním příspěvku by mohl hlásit chybu zaplnění disku jedině v případě, že by disk byl plný už před začátkem zápisu. Kdyby se disk zaplnil už voláním té funkce fwrite(), selhalo by už druhé volání fwrite(), a tam žádný výpis chybového kódu není. Programátor to musí vidět na první pohled. Takže vaše snaha najít nějaký programovací jazyk, kde byste vůbec nemusel programovat, protože vám to nejde, je pochopitelná. A to ještě pořád nejsem drzý.

Jaký chování? Že není spokojený s radou, která prostě nefunguje? Když by se všichni chovali jako on, tak by bylo krásně na foru.
Jestli ta rada funguje nebo nefunguje by mohl zjistit teprve tehdy, až by ten kód opravil. Což se nestalo. Pokud nepochopil, v čem je problém, mohl se slušně zeptat. Což se také nestalo.

Víš, problém jsi tu ty, ne ostatní.
Můj problém je, že se tu vybavuju s někým, kdo si o sobě myslí, že je mistr světa, a přitom si ani neumí zavázat tkaničky. Pozdravujte Jéčko na ignorlistu.


Ladislav Michl

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #76 kdy: 02. 07. 2018, 22:39:22 »
No a včil mudrujte.
No tak hurá, aspoň někdo to zkusil! Odtud:
https://github.com/php/php-src/blob/master/ext/standard/file.c#L1189
a odtud:
https://github.com/php/php-src/blob/master/main/streams/streams.c#L1189
#define php_stream_write(stream, buf, count)   _php_stream_write(stream, (buf), (count))
to vypadá, že se pracuje s FILE, nikoliv s fd.

Byl byste ochotný udělat ještě jeden pokus, kdy se soubor otevře pomocí dio_open() a odtud se teprve získá stream?

A. F.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #77 kdy: 02. 07. 2018, 23:04:40 »
No a včil mudrujte.
No tak hurá, aspoň někdo to zkusil! Odtud:
https://github.com/php/php-src/blob/master/ext/standard/file.c#L1189
a odtud:
https://github.com/php/php-src/blob/master/main/streams/streams.c#L1189
#define php_stream_write(stream, buf, count)   _php_stream_write(stream, (buf), (count))
to vypadá, že se pracuje s FILE, nikoliv s fd.

Byl byste ochotný udělat ještě jeden pokus, kdy se soubor otevře pomocí dio_open() a odtud se teprve získá stream?
Určitě!
Ale bohužel. Mám PHP verzi 5.6, tohle je pro < 5.1 (dle dokumentace). Pro jistotu jsem to i tak zkusil, člověk nikdy neví, ale už tam není no.

(Degradovat na 5.1 se mi nechce, a i kdyby to pomohlo, tak to stejně nebudu moct použít.)
« Poslední změna: 02. 07. 2018, 23:08:29 od andreaw.fean »

A. F.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #78 kdy: 02. 07. 2018, 23:07:49 »
Na což se neptal, nesouviselo to s tím na co se ptal, a ani to nijak nepomohlo s jeho problémem. Rada na nic.
Vy jste stále ještě nepochopil, jaký problém se tu řeší. Takže vaše názory na to, co pomohlo a co ne, jsou k ničemu.
Tak jeho rada (https://forum.root.cz/index.php?topic=18906.msg272378#msg272378) sice nebyla moc povzbudivá, ale alespoň byla k věci a normální.

Ladislav Michl

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #79 kdy: 02. 07. 2018, 23:30:40 »
Mám PHP verzi 5.6, tohle je pro < 5.1 (dle dokumentace). Pro jistotu jsem to i tak zkusil, člověk nikdy neví, ale už tam není no.

(Degradovat na 5.1 se mi nechce, a i kdyby to pomohlo, tak to stejně nebudu moct použít.)

Pardon. Přiznám se, že jsem nevšiml, že tahle část je obsolete. Teoreticky by mohlo jít použit eio_open() z https://pecl.php.net/package/eio a protože se tím krmí libev, předpokládám, že vrací file descriptor. Bez záruky, do kódu jsem se nedíval.


A. F.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #80 kdy: 03. 07. 2018, 00:18:02 »
Pardon. Přiznám se, že jsem nevšiml, že tahle část je obsolete. Teoreticky by mohlo jít použit eio_open() z https://pecl.php.net/package/eio a protože se tím krmí libev, předpokládám, že vrací file descriptor. Bez záruky, do kódu jsem se nedíval.

Tak teda to EIO jsem zkusil. Funguje to hezky. Při vyčerpání místa to vrátí chybu, a tu lze přečíst pomocí eio_get_last_error(). Takhle by se mi to líbilo u to fwrite(), škoda, že to neumí no.

L.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #81 kdy: 03. 07. 2018, 05:31:17 »
Mohl byste být přesnější, co z toho, co jsem radil, byla hovadina?

Prakticky všechno. Nejdřív jsi se tu točil na nějakém částečném zápisu, což ale problém vůbec nebyl. Ono totiž PHP, jak se zdá, tu smyčku dělá už interně ve funkci, kterou volá ten fwrite(): https://github.com/php/php-src/blob/master/main/streams/streams.c#L1080

Dál jsi psal:

Pokud by vám i posix_get_last_error() vracela, že k žádné chybě nedošlo, máte smůlu, protože PHP mezitím zavolalo nějakou jinou POSIXovou funkci, která výsledek volání write() překryla.

Kdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.

Kód v prvním příspěvku by mohl hlásit chybu zaplnění disku jedině v případě, že by disk byl plný už před začátkem zápisu. Kdyby se disk zaplnil už voláním té funkce fwrite(), selhalo by už druhé volání fwrite(), a tam žádný výpis chybového kódu není.

Hele a tohle jsi v praxi ověřoval? Řek bych že ne a zase jen plácáš ty svoje neověřený teoretický nesmysly. PHP prostě žádný chybový kód nenastaví. Ani při prvním, ani při jakémkoli dalším volání.


Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #82 kdy: 03. 07. 2018, 07:49:25 »
Nejdřív jsi se tu točil na nějakém částečném zápisu, což ale problém vůbec nebyl. Ono totiž PHP, jak se zdá, tu smyčku dělá už interně ve funkci, kterou volá ten fwrite(): https://github.com/php/php-src/blob/master/main/streams/streams.c#L1080
Normální je programovat proti specifikaci funkce, ne proti tomu, jak je aktuálně naimplementovaná. Když je zdokumentováno, že funkce vrací počet zapsaných bajtů, plyne z toho, že nemusí zapsat vše (zvlášť když je to obvyklé chování funkcí zapisujících do streamu). Když si někdo zjistí, že zrovna v jeho verzi ta funkce zapíše vše nebo vrátí chybu, naprogramuje podle toho svůj kód, a pak se chování funkce změní (ale bude pořád v souladu s dokumentací), bude mít v programu chybu, v tomto případě navíc těžko odhalitelnou (protože bude nastávat jen někdy).

Že ta PHP funkce fwrite() funguje úplně jinak, než je popsáno v dokumentaci, je dost zásadní chyba. Pokud to tazatel věděl, měl to napsat. Jinak bývá dobrým zvykem hledat chybu nejprve ve svém kódu a teprve pak v knihovnách. A ten kód andreaw.fean je špatně, a to i v případě, když bude počítat s tím, že tu smyčku dělá fwrite() interně.

Kdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.
Dalo se předpokládat, že fwrite() interně volá nativní funkci write(), která je definovaná POSIX standardem, a která v případě neúspěchu ukládá chybový kód do errno. Funkce posix_get_last_error() mohl být způsob, jak errno přečíst.

Hele a tohle jsi v praxi ověřoval? Řek bych že ne a zase jen plácáš ty svoje neověřený teoretický nesmysly. PHP prostě žádný chybový kód nenastaví. Ani při prvním, ani při jakémkoli dalším volání.
Ten kód, tak jak je napsaný, nejdřív předpokládá, že když se nezapíše vše, je to hned chyba, a vzápětí se pokusí zapsat ještě zbytek. Při jaké konstelaci tenhle kód dává smysl?

Ověřit to chování měl andreaw.fean, on měl prostředí, kde k nějaké chybě docházelo. Když se mně nepodaří nasimulovat případ, že by fwrite() vrátilo menší počet zapsaných bajtů, než byl počet bajtů k zápisu, v žádném případě to neznamená, že mám počítat s tím, že to nemůže nikdy nastat. Přesně na základě takovýchto předpokladů vznikají programy, které pak různě náhodně padají.

To, že PHP žádný chybový kód nenastaví bylo potřeba zjistit – buď zkoumáním zdrojáků, nebo testem. Ten test je ovšem potřeba provést tak, aby vůbec byla šance, že tu chybu nastaví. Tvrdit, že funkce fwrite() chybu nenastavuje, na základě kódu, který nastavení chyby neumí zjistit, je dost odvážné. A nic na tom nemění fakt, že se nakonec (úplně jiným způsobem) ukázalo, že fwrite() opravdu chybu nenastavuje.

Kdyby se funkce fwrite() chovala tak, jak je popsané v dokumentaci, ten kód andreaw.fean by se choval přesně tak, jak popisoval – tj. žádnou chybu by to nevypsalo. Stačilo by ten kód opravit. Že se nakonec fwrite() chová úplně jinak je dost problém, a vzhledem k této diskusi je to jen náhoda. Kdyby andreaw.fean ten svůj kód opravil, vzápětí by se přišlo na to, že fwrite() funguje špatně – a mohlo by se to řešit. Místo toho se tu pořád dokola řešilo, že vlastně nikdo neví, jak vlastně ten kód funguje. Vždyť andreaw.fean ani nebyl schopen napsat, jestli mu to volání fwrite() vrací FALSE, 0 nebo nějakou kladnou hodnotu. To by hledání chyby značně urychlilo, protože kdyby opakovaně vracelo 0, bylo by jasné, že se to chová jinak, než je zdokumentováno.

Nakonec se tedy strašně dlouhou a klopotnou cestou skládání náhodných úryvků kódu dospělo k řešení, se kterým je andreaw.fean spokojen. Je ale velmi smutné, kolik lidí tady v diskusi vůbec nepochopilo, proč je ten původní kód špatně, a vlastně jim je úplně jedno, že to nechápou – prostě ten kód zkouší náhodnými výstřely měnit, a když jim to jednou udělá, co chtějí, jsou spokojení, a mají pocit, že je kód správně. A ještě mají pocit, jací jsou machři. Už se vůbec nedivím, že BoneFluteovi jednotkové testy vůbec nepomáhají – pokud testuje jenom to, co mu zrovna spadlo pod rukama, a vůbec nechápe, co jeho kód vlastně dělá a kde jsou potenciální chyby, jednotkové testy mu opravdu nijak nepomůžou.

Lol Phirae


L.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #84 kdy: 03. 07. 2018, 08:22:58 »
Stále kvoká, stále kvoká...

Je to tak. Pevně doufám, že nikde neprogramuje a pokud ano, tak lituju jeho spolupracovníky. U mě by takový nemehlo vyletělo na hodinu zavřenýma dveřma a ještě bych mu je dal k úhradě.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #85 kdy: 03. 07. 2018, 09:23:45 »
Je to tak. Pevně doufám, že nikde neprogramuje a pokud ano, tak lituju jeho spolupracovníky. U mě by takový nemehlo vyletělo na hodinu zavřenýma dveřma a ještě bych mu je dal k úhradě.
Dobře, uznávám, rozumíte tomu lépe než já. Můžete mi tedy některé věci na tom kódu uvedeném v dotazu vysvětlit? Napíšu i nijaké příklady možných odpovědí, aby bylo srozumitelnější, na co se ptám – těmi příklady odpovědí se ale nenechte zmást, ty jsou evidentně špatně.

  • Jaký je význam toho druhého volání fwrite() – na řádku 14? Myslím tím jakou situaci ošetřuje. Např. by odpověď mohla být: „Ošetřuje situaci, kdy první volání fwrite() na řádku 9 je jen částečně úspěšné, zapíše jen část dat, ale je možné, že se při dalším pokusu podaří zapsat další část – např. pokud by při prvním volání byl disk plný, ale před druhým voláním by se místo uvolnilo.“
  • V jakém případě dojde program k tomu druhému volání fwrite() – na řádku 14? Jaké budou invarianty programu? Např.: „První volání fwrite() na řádku 9 vrátilo hodnotu FALSE nebo 0.“ Nebo.: „První volání fwrite() na řádku 9 vrátilo hodnotu počet zapsaných bajtů, větší než 0 a menší než délka $s.“
  • Jaký bude výsledek volání programu, pokud před prvním voláním fwrite() (na řádku 9) bude na cílovém disku volné místo, ale ne tolik, aby se tam vešlo celé $s, a před druhým voláním fwrite() (na řádku 14) se nějaké místo na disku uvolní? Zajímá mne především co bude aplikace vypisovat a co bude zapsané v cílovém souboru.

ffd

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #86 kdy: 03. 07. 2018, 12:47:14 »
Stále kvoká, stále kvoká...

Je to tak. Pevně doufám, že nikde neprogramuje a pokud ano, tak lituju jeho spolupracovníky. U mě by takový nemehlo vyletělo na hodinu zavřenýma dveřma a ještě bych mu je dal k úhradě.

No tak strasne to asi nebude, ale v tymu nebo ve firme bych ho nechtel. At si nekde cosi patla na kontrakt, kdyz je s tim zakaznik happy, proc ne. Ale jinak domluva s nim musi byt ukrutne slozita.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #87 kdy: 03. 07. 2018, 20:27:53 »
To je vtipná představa, že by junioři ve zkušební době (protože po zkušebce už musí takhle očividné chyby vidět sám) vyhazovali seniory, když by si senior dovolil upozornit na chybu v kódu juniora.

Ale je teda dost smutné vidět tu několik lidí, kteří si o sobě očividně myslí bůhví co a myslí si, že umí programovat, kterým nevadí program pro zápis do souboru, který:
  • úspěšně zapíše všechna data a vypíše chybu, že se podařilo zapsat jenom část dat
  • skončí s chybou, že se nepodařilo všechna data zapsat, přestože na disku je dost místa a ani nic jiného nebrání všechna data zapsat

Navíc kdyby ta funkce fwrite() uměla nějak signalizovat příčinu chyby, při zápisu na zcela plný disk by program správně oznámil, že disk je plný, ale kdyby se disk zaplnil teprve v průběhu zápisu, program by v lepším případě (pokud by andreaw.feana něco osvítilo a počítal by s tím, že se při zjištění chyby může dozvědět, že k žádné chybě nedošlo) oznámil, že došlo k nečekané chybě.

Stejně by mne ale zajímalo, kdyby L., ffd, BoneFlute nebo andreaw.fean odpověděli na ty tři otázky, které jsou v mém předchozím komentáři. Zajímalo by mne, jestli aspoň chápete význam jednotlivých řádků kódu, jenom si nedokážete spojit dohromady, co to dělá, když se ty řádky provádí postupně za sebou, a nebo jestli vám uniká i význam těch jednotlivých řádků.

unicode

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #88 kdy: 04. 07. 2018, 03:57:43 »
Citace
Kdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.

Přímo v dokumentaci http://php.net/manual/en/function.posix-get-last-error.php se používá v příkladu stream_select(), takže to s tím "posix_" prefixem není pravda. Zbytek se mi nechce hledat, ale řekl bych, že ta funkce logicky vrací "errno".

A. F.

Re:Zjištění chyby při neúspěchu fwrite()
« Odpověď #89 kdy: 04. 07. 2018, 20:14:37 »
Citace
Kdybys měl alespoň trochu ánunk o tom, o čem píšeš, tak by ti došlo, že posix_get_last_error() je z POSIX modulu, tedy funguje jen pro jeho funkce. Ty se vyznačují tím, že mají prefix posix_. No a jak si můžeš všimnout, funkce fwrite() ten prefix nemá. Takže na ni posix_get_last_error() logicky nefunguje a tedy to co jsi psal, je totální hovadina.

Přímo v dokumentaci http://php.net/manual/en/function.posix-get-last-error.php se používá v příkladu stream_select(), takže to s tím "posix_" prefixem není pravda. Zbytek se mi nechce hledat, ale řekl bych, že ta funkce logicky vrací "errno".
Zkoušel jsem to. Ty funkce bohužel nefachají. Ani jedna.