gzinflate(): data error #340

Open
Mermouy opened this Issue Jan 27, 2014 · 42 comments

Projects

None yet
@Mermouy
Mermouy commented Jan 27, 2014

En ouvrant mon lecteur ce matin j'ai droit aux erreurs suivantes:

Warning: gzinflate(): data error in /media/donnees/www/rss.youm.org/htdocs/index.php on line 2440

Warning: Invalid argument supplied for foreach() in /media/donnees/www/rss.youm.org/htdocs/index.php on line 2847

Warning: Invalid argument supplied for foreach() in /media/donnees/www/rss.youm.org/htdocs/index.php on line 2500

Il semblerait que j'ai un problème avec la compression non? Je ne sais pas ce que j'ai pu modifier pour obtenir cette erreur puisque KrissFeed tourne maintenant depuis quelques semaines sur mon serveur, j'ai posté ma configuration dans #339 (comment) mais je sais que tu n'es pas spécialement au jus d'nginx, mais au cas où quelqu'un passe par là et possède la solution/explication toute faîte, je prend, je n'ai pas trop le temps cette semaine, j'essaierai d'y trifouiller en soirée...
@+

@tontof
Owner
tontof commented Jan 27, 2014

Arf c'est malheureusement lié à un problème de corruption du fichier data.php (#269 #268) et je n'ai aucune piste sur les raisons du problème. Ce n'est pas lié à nginx car c'est arrivé chez d'autres personnes. Tu risques malheureusement de ne pas pouvoir faire grand chose. Il y a une sauvegarde de ton opml dans le dossier data pour réimporter tes flux.
Si tu peux m'envoyer sur tontof à free.fr une archive de ton dossier data, je peux essayer de regarder si je peux récupérer ton data.php mais il y a peu de chance. Ça me permettra par contre de voir quelle est vraiment l'erreur car, il y en a certaines qui peuvent se corriger.
Il faudrait que tu regardes tes logs pour voir si tu as des erreurs particulières avant le gzinflate.

@lucasg
lucasg commented Jan 27, 2014

La même erreur vient de m'arriver il y a quelques jours (la dernière datant d'il y a quelques semaines) et j'ai remarqué un point commun : à chaque fois mon serveur a subit une coupure de courant.
Etant un bourrin dans l'âme, ma tâche cron met à jour les flux toutes les minutes, et il se peut que la coupure soit tombée pendant l'écriture.

mes 2c.

@Mermouy
Mermouy commented Jan 28, 2014

Merci, @lucasg en effet le serveur a déconnecté queques minutes la nuit d'avant...
@tontof : J'envoie tout ça à l'instant par mail, merci pour ces réponses rapides!

@tontof
Owner
tontof commented Jan 28, 2014

Arf c'est embêtant si ça vient de ça parce que je ne vois pas trop comment je peux corriger ça dans KrISS feed.

Dans le même style, il y avait la fin du processus PHP qui intervient pendant l'écriture (par exemple au bout de 30 s) #281 (comment)
Normalement ce problème est corrigé dans la version dev (dans src)

Il va peut-être falloir que j'étudie l'alternative sqlite en plus de celle actuelle qui ne nécessite pas de bibliothèque supplémentaire

@Nodd
Nodd commented Jan 28, 2014

Sinon, tu écris dans un data_tmp.php, et à la fin tu remplaces le data.php par data_tmp.php. L'écrasement du fichier sera bien plus rapide que la compression donc il y a moins de chance que ça merde.
Si tu veux vraiment assurer le coup, tu crées un data_tmp.php, tu copies le data.php dans data_sav.php, entuite tu changes data_tmp.php en data.php et enfin tu vires (ou pas) data_sav.php. Comme ça même si ça coupe quelque part, tu as toujours un exemplaire valide du data.php quelque part.

@lucasg C'est vraiment vraiment bourrin toutes les minutes. Aussi bien pour ton serveur que pour les serveurs en face...

@tontof
Owner
tontof commented Jan 28, 2014

@Nodd ta proposition pourrait effectivement fonctionner mais ce qui me dérange dans cette approche est la pénalisation pour beaucoup de personnes pour éviter le problème chez certains (sans être sûr à 100% de l'origine du problème par ailleurs). Quand j'entends pénalisation, je veux parler du temps d'exécution car c'est effectivement gourmand d'écrire plusieurs fichiers. C'est pourquoi je pense qu'il est préférable d'envisager une autre approche avec un truc du style PDO/sqlite. Ça nécessite l'installation d'une bibliothèque particulière, mais ce ne serait indispensable que pour ceux qui ont ce genre de problème.
L'avantage que je vois à cette approche est l'amélioration du code qui nécessitera une bonne gestion du modèle pour pouvoir gérer avec plusieurs approches (fichiers comme maintenant et PDO/sqlite).
Rien est encore décidé et je n'ai malheureusement pas le temps de m'en occuper pour le moment :-(

@Sbgodin
Sbgodin commented Jan 28, 2014

@tontof attention à Sqlite. Ça devrait résoudre le problème de corruption de données mais en introduire un autre : une plus grande latence. En effet, Sqlite verrouille toute la base d'un coup. Il fait ça de façon intelligente en permettant de lire à plusieurs (et personne n'écrit) et de réserver sa place pour écrire à l'avance. Il reste que c'est quand même toute la base de données qui est verrouillée. Cela implique des délais.

PDO (ainsi que l'utilisation de bases de données serveur en général) me semble être la meilleure solution. Les verrouillages ne concernent pas toute la base et c'est optimisé pour. Évidemment, il faut le SGBD derrière.

Une astuce : php est capable d'utiliser des mutex permettant de mettre une modification de fichier en section critique. Quand un processus prend le mutex, un autre doit attendre. Mais ça ne marche que sous Linux (tout système POSIX à ma connaissance).

@tontof
Owner
tontof commented Jan 28, 2014

@Sbgodin merci de l'info.
Par rapport à sqlite je serai curieux de comparer avec l'approche fichier brut actuel parce que je pense qu'il a les mêmes problèmes de latence (le fichier data.php est considéré comme un bloc). Mais PDO me semble aussi plus intéressant et permettrait de ne pas simplement se limiter à sqlite.

Après, je n'arrive pas trop à savoir quelles seront les conséquences par rapport à la version actuelle. En terme de modification de codes et surtout conséquence sur le temps d'exécution.

@Sbgodin
Sbgodin commented Jan 28, 2014

Pour autant que j'en sais, il n'y a pas de verrou sur data.php d'où les soucis actuels certainement. Par contre, ça lit très vite, forcément. Le problème est qu'un outil de syndication lit souvent quand on parcours les flux et écrit souvent et vite quand ils sont mis à jour. Sans parler des modifications induites par l'utilisateur comme marquer lu un article.

Utilisant massivement Leed avec Mysql, je ne constate aucun ralentissement. J'arrive à ma limite en terme de lecture de flux par rapport à l'arrivée des nouvelles infos, avec plus de 120 flux. Mais la masse d'information est ridicule par rapport à ce que Mysql est fait pour traiter. Mais bon, il faut la ba-base de données avec.

PDO permet d'utiliser sqlite, mysql et quelques autres. C'est une abstraction pour la persistance des données. Ce qui change avec mysql, et les autres SGBD, c'est qu'il y a un processus dédié qui gère la base de données, les verrous, les transactions,etc. C'est donc forcément béton. L'inconvénient d'utiliser PDO plutôt qu'une base de données native est qu'on se prive des sucreries propres aux SGBD. Par contre, on est plus générique et on peut se brancher sur plusieurs type de bases au choix.

@Nodd
Nodd commented Jan 29, 2014

Si je ne dis pas de bêtises, c'est l'écriture du data.php qui est lente, mais la copie des fichiers doit être rapide ? De plus dans ma première approche tu n'écris qu'un seul fichier qui est ensuite renommé, ça ne doit pas induire de ralentissement. Dans la deuxième approche il faut en écrire un et en copier un, le reste c'est du renommage donc ultra-rapide. Cela dit c'est vrai que ça fait du bricloage plus qu'autre chose.

@Nono-m0le
Contributor

Le retour du gzinflate ...

Je viens de perdre mes flux :(

Par contre, même si le backup du .opml est bien sympa, j'ai toujours encore les erreurs suivantes :

Notice: Undefined index: items in /mnt/nfs/home/rss/public_html/index.php on line 498

Warning: Invalid argument supplied for foreach() in /mnt/nfs/home/rss/public_html/index.php on line 498

@tontof
Owner
tontof commented Sep 22, 2014

Je ne suis pas sûr de bien comprendre ton «j'ai toujours encore les erreurs suivantes»
Après la perte du data, il faut supprimer le fichier data.php corrompu avant de réimporter avec le opml de sauvegarde.

Cela faisait longtemps que je n'avais pas eu de retour sur cette erreur, je n'ai toujours pas de problème de mon côté, j'ai réfléchi à une autre solution de stockage mais je ne sais pas quand j'aurai le temps de le mettre en place. Pas d'erreur particulière dans les logs pour essayer d'avoir une idée de piste. Quel est la taille du fichier data.php corrompu ?

@Nono-m0le
Contributor

Entre temps, j'ai trouvé la cause. Mon disk était full ! 

-------- Message d'origine --------
De : tontof notifications@github.com
Date : 22/09/2014 13:01 (GMT+01:00)
A : tontof/kriss_feed kriss_feed@noreply.github.com
Cc : Nono nono@m0le.net
Objet : Re: [kriss_feed] gzinflate(): data error (#340)

Je ne suis pas sûr de bien comprendre ton «j'ai toujours encore les erreurs suivantes»
Après la perte du data, il faut supprimer le fichier data.php corrompu avant de réimporter avec le opml de sauvegarde.

Cela faisait longtemps que je n'avais pas eu de retour sur cette erreur, je n'ai toujours pas de problème de mon côté, j'ai réfléchi à une autre solution de stockage mais je ne sais pas quand j'aurai le temps de le mettre en place. Pas d'erreur particulière dans les logs pour essayer d'avoir une idée de piste. Quel est la taille du fichier data.php corrompu ?


Reply to this email directly or view it on GitHub.

!DSPAM:542001a617065251320655!

@tontof
Owner
tontof commented Sep 22, 2014

Ah ben bravo ! C'est en effet une chose qui n'est pas prise en compte.

@Seb-C
Seb-C commented Oct 20, 2014

Je viens d'avoir cette erreur aussi :( .

J'ai l'impression que tous ceux qui l'ont ont eu un incident pendant l'écriture du fichier data (disque plein, coupure de courant ...). Une idée pour éviter le problème serait donc d'écrire les données dans un fichier data2 (par exemple), puis, uniquement à la fin du processus d'écriture, supprimer data.php et renommer l'autre. En cas d'anomalie, on aurait un fichier data intact (mais pas mis a jour) et un fichier data2 corrompu, mais qui serait de toute façon écrasé lors du chargement suivant.

Le seul risque restant serait une anomalie après suppression de data, mais avant de renommer data2. Dans ce cas là on aurait toujours un fichier intègre (data2) à récupérer. Le processus pour supprimer/renommer des fichiers prenant moins de temps que l'écriture, on réduirait d'autant la probabilité d'avoir un incident au mauvais moment.

@tontof
Owner
tontof commented Oct 20, 2014

Arf désolé pour ton data...

Le problème lié à l'ajout d'un fichier data2 c'est que ça risque d'augmenter considérablement le temps d'exécution du script pour un problème qui même si il apparaît chez certains semblent relativement isolé cf #340 (comment)

@cyberic99

"un problème qui même si il apparaît chez certains semblent relativement isolé"
Oui mais c'est quand même un problème assez grave vu qu'il fait perdre toutes les données d'un coup...
Sinon, est il possible:

  • soit toutes les 100 écritures par exemple, de faire un backup
  • soit de faire un data1.php, data2.php etc, et de tourner?
    en cas de probleme on peut toujours recupérer quelque chose...
@tontof
Owner
tontof commented Oct 20, 2014

Oui je suis bien d'accord pour la perte définitive.

Par contre ton histoire de faire tourner est très intéressante, imaginer faire un truc qui enregistre avec la date sur 3 derniers roulements :

  • data_20141020_164915.php
  • data_20141020_165112.php
  • data_20141020_165924.php

Ce qui est embêtant avec cette méthode c'est qu'il est difficile de récupérer le dernier fichier sans ajouter un peu de complexité.
À la lecture on cherche toujours le dernier, à l'écriture on ajoute une nouvelle entrée avec la date et on supprime le plus ancien pour en avoir toujours 3.

Cette idée est peut-être à garder sous le coude mais je l'imaginerais bien avec un plugin.

@cyberic99

Le nom du dernier fichier peut être enregistré dans lastfile.php par exemple.
Si on a une erreur en lisant lastfile, alors il faut faire un readdir() etc.
mais la plupart du temps cela devrait marcher, car des ecritures comme cela de moins de 4ko sont atomiques sur la plupart des filesystems.

@tontof
Owner
tontof commented Oct 20, 2014

"la plupart du temps" :-) comme le code actuel la plupart du temps il fonctionne très bien :-)

Je ne sais pas quand je vais trouver du temps pour ça. Le dernier commit date de décembre 2013 :-(

@cyberic99

oui, on peut éventuellement tomber sur une race condition
Dans le pire des cas, les données ne seront pas tout à fait à jour. Mais au moins il restera des données ;-)

@Nono-m0le
Contributor

Je ne peux que 'plussoyer' cette idée ! 

-------- Message d'origine --------
De : cyberic99 notifications@github.com
Date : 20/10/2014 17:44 (GMT+01:00)
A : tontof/kriss_feed kriss_feed@noreply.github.com
Cc : Nono nono@m0le.net
Objet : Re: [kriss_feed] gzinflate(): data error (#340)

oui, on peut éventuellement tomber sur une race condition
Dans le pire des cas, les données ne seront pas tout à fait à jour. Mais au moins il restera des données ;-)


Reply to this email directly or view it on GitHub.

!DSPAM:54452dc317061946510125!

@cyberic99

mais c'est plus facile à dire qu'à faire, on sait bien tontof...

@tontof
Owner
tontof commented Oct 20, 2014

En fait j'ai envie d'en profiter pour utiliser un peu plus de Dependency Injection.
Cela permettrait plus de souplesse dans le code. À voir...

@Seb-C
Seb-C commented Nov 4, 2014

Cette nuit j'ai encore une fois perdu toutes mes données à cause de ce bug.

J'ai du mal à comprendre la logique de dire que "ça risque d'augmenter considérablement le temps d'exécution du script" alors qu'en parallèle tu es favorable à une rotation des fichiers qui est encore plus lourde.

L'impact d'un fichier data2.php resterait infime en terme de performances. Le seul impact serait (temporairement) au niveau de l'espace disque, ce qui me semble négligeable. Le reste, ce sont des manipulations au niveau du système de fichiers qui ne prendront presque pas de ressources.

A la limite, on pourrait ajouter une option pour donner le choix d'activer cette possibilité.

@tontof
Owner
tontof commented Nov 4, 2014

Dans les 2 cas cela alourdit l'exécution du script. D'ailleurs je pense que c'est à peu près équivalent, sauf que dans un cas tu tournes sur 2 fichiers et dans l'autre sur 3 ou plus.

J'ai une bonne nouvelle (j'espère)... je viens d'ajouter une branche data_fix pour faire un test.
Je n'ai pas du tout étudier l'impact sur les performances mais j'ai ajouté la création d'un fichier data.php.php en cas de lecture réussie.

En gros si la lecture se déroule bien on fait une copie de data.php en data.php.php
Si la lecture se passe mal on essaye de lire data.php.php à la place.

Je laisse tester ceux qui ont des problèmes et on verra si cela semble corriger ou pas ce problème.
(Je n'ai que testé l'erreur associée à gzinflate)

Pour ceux qui veulent tester:
https://raw.githubusercontent.com/tontof/kriss_feed/data_fix/src/index.php

@cyberic99

@tontof il se passe quoi s'il y a plusieurs copies de data.php en data.php.php, en même temps?

@tontof
Owner
tontof commented Nov 4, 2014

Euh je ne suis pas sûr d'avoir bien compris mais normalement il ne peut pas y avoir plusieurs copies dans dans data.php.php.
En gros ça ne garde que la dernière copie du data.php valide.

@cyberic99

Mais si deux threads apache font une lecture en même temps?
moi ca m'arrive super souvent d'ouvrir un sous dossier dans une nouvelle fenêtre

@tontof
Owner
tontof commented Nov 5, 2014

même si tu as 2 fenêtres c'est toujours le même fichier derrière, ça ne devrait donc rien changer. Tu auras bien toujours 1 seul fichier data.php et 1 seul fichier data.php.php

@cyberic99

Quand tu marques un article comme lu, par exemple, alors que sur un autre onglet, ou avec le cron, tu rafraichis la liste des feeds, est ce qu'à ce moment là il peut y avoir plusieurs accès simultanés à data.php?

@tontof
Owner
tontof commented Nov 5, 2014

ben en fait pas plus que comme c'est le cas actuellement

@franck-tomek

Je n'avais pas suivi les discussions ici. J'ai toujours le souci régulièrement, je vais installer cette version pour voir si ça corrige le souci.

@Seb-C
Seb-C commented Apr 14, 2015

Depuis le temps j'avais un peu oublié ce topic, mais je confirme ne plus avoir eu de problèmes depuis ce correctif.

@tontof
Owner
tontof commented Apr 21, 2015

Merci pour les retours :-)

@Metal-Mighty

Juste pour info l'erreur a pop chez moi aujoud'hui avec la dernière version dev. Je n'ai aucune idée de ce qui peut en être la cause malheureusement :/

@Metal-Mighty

Dernière dev, je l'utilise pour la correction que tu as effectué suite à l'issue #361 .
Du coup j'ai supprimé le data.php et réimporté l'opml sauvegardé dans le dossier data/ (je ne savais pas qu'il en faisait un, ça sauve la vie!)

@tontof
Owner
tontof commented Oct 13, 2015

Je ne sais pas si tu as souvent l'erreur, mais j'ai mis à jour la branche pour intégrer les modifs de #361
Tu peux donc utiliser patch : https://raw.githubusercontent.com/tontof/kriss_feed/data_fix/src/index.php sans problème

@Metal-Mighty

Non c'est la première fois que ça m'arrive depuis que je l'utilise (depuis l'annonce de la fermeture de Google Reader... Ca commence à dater!), donc ce n'est pas si critique que ça, mais cela peut s'avérer problématique pour quelqu'un qui ne sait pas qu'il existe un backup de son opml.

J'ai remplacé ma version par le patch, merci !

@emporeso2
emporeso2 commented Sep 17, 2016 edited

@Bonjour,
je viens de me retrouver avec le meme probleme ,depuis ce post y a t il eu une solution ?
Que faut-il faire dans ce cas ?

Warning: gzinflate(): data error in /xxx/index.php on line 89
Warning: Invalid argument supplied for foreach() in /xxx/index.php on line 498
Warning: Invalid argument supplied for foreach() in /xxx/index.php on line 150

@tontof
Owner
tontof commented Sep 19, 2016

Pas vraiment de solution si ce n'est la proposition:
https://raw.githubusercontent.com/tontof/kriss_feed/data_fix/src/index.php
Pas grand chose à faire dans ce cas malheureusement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment