Libelektra: mmapstorage ne fonctionne pas avec l'exportation kdb

Créé le 15 févr. 2019  ·  22Commentaires  ·  Source: ElektraInitiative/libelektra

Étapes pour reproduire le problème

kdb set user/tests/hello world
#> Create a new key user/tests/hello with string "world"

kdb export user/tests/hello mmapstorage > test.mmap

résultat attendu

Un fichier appelé test.mmap est créé, qui peut être réimporté avec kdb import .

Résultat actuel

Un fichier vide appelé test.mmap est créé et le message suivant est imprimé (inclut les journaux de ENABLE_LOGGER ):

src/plugins/mmapstorage/mmapstorage.c:944:libelektra_mmapstorage_LTX_elektraPluginset: could not unlink
src/plugins/mmapstorage/mmapstorage.c:1003:libelektra_mmapstorage_LTX_elektraPluginset: strerror: Permission denied
Sorry, the error (#9) occurred ;(
Description: Insufficient permissions to open configuration file for writing. You might want to retry as root.
Reason: Permission denied
Ingroup: kdb
Module: 
At: /home/klemens/data/bsc/libelektra/src/plugins/mmapstorage/mmapstorage.c:1004
Mountpoint: user
Configfile: /dev/stdout

Information système

  • Version Elektra: maître

Informations complémentaires

~ Fonctionne lorsque kdb export est appelé en tant que root. ~ (EDIT: voir le commentaire ci-dessous) kdb export user/tests/hello mmapstorage test.mmap fonctionne également, mais est une fonctionnalité complètement non documentée de kdb export . Donc, un meilleur message d'erreur et une documentation mise à jour pourraient être tout ce dont nous avons besoin.

bug

Commentaire le plus utile

Merci pour votre réponse!

Les messages d'erreur mmap peuvent être trompeurs.

Veuillez améliorer les messages d'erreur.

À ma connaissance, cela ne fonctionnera pas sur stdout. Cela ne fonctionne pas non plus avec les tuyaux

Veuillez ajouter ces informations aux messages d'erreur.

Les solutions ci-dessus ne changent pas beaucoup la logique de mmapstorage.

Comme votre plugin est actuellement le seul affecté, il est logique que vous fassiez la statistique et copiez tout si nécessaire. Ensuite, nous pourrions fermer ce problème sans modifications plus importantes du cadre.

Tous les 22 commentaires

Merci d'avoir essayé ceci et pour ce rapport détaillé!

Donc, un meilleur message d'erreur et une documentation mise à jour pourraient être tout ce dont nous avons besoin.

Oui, je suis entièrement d'accord.

Peut-être devrions-nous même avoir un serializable dans infos / status # 666 et échouer explicitement si le fichier est / dev / stdout? ( @mpranj Ou y a-t-il un moyen de détecter si un fichier n'est pas mmapable? Est-ce vraiment identique à une permission refusée?)

En regardant le code (et le message d'erreur), je pense que le problème actuel est que nous ne pouvons pas appeler unlink sur stdout sans accès root. De plus, open échouera probablement aussi, car stdout est déjà ouvert. Et si stdout est mmapable ou non dépend de ce à quoi stdout est connecté je pense.
L'utilisation de fstat(fileno(stdout), &stat) pour vérifier s'il s'agit d'un fichier normal peut fonctionner. Peut-être que isatty(3) fonctionne également.

Dans tous les cas, nous pourrions simplement vérifier si le fichier de sortie est /dev/stdout (ou CON pour _WIN32 ) et créer un fichier temporaire à utiliser avec mmap et ensuite simplement le copier dans stdout . Ce serait bien sûr plus lent mais nous conserverions la possibilité de rediriger la sortie de kdb export .

Peut-être devrions-nous même avoir un serializable dans infos / status # 666 et échouer explicitement si le fichier est / dev / stdout?

Si quoi que ce soit, j'aurais un statut humanreadable et refuserais d'exporter vers un stdout tty, si le format n'est pas lisible par l'homme.

Fonctionne lorsque kdb export est appelé en tant que root.

Je reprends ça ... N'ESSAYEZ PAS CELA! L'appel de kdb export <something> mmapstorage tant qu'utilisateur root (même si stdout est redirigé) détruit /dev/stdout . L'utilisation de /dev/stdout (par exemple via fopen ) ne fonctionnera pas sur votre système tant que vous n'aurez pas recréé le lien symbolique par défaut avec sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1 .

Je pense que la meilleure solution est que kdb export et kdb import fonctionnent toujours sur des fichiers temporaires. Alors kdb export sera plus similaire à ce que fait KDB. Cela résoudrait le problème de dissociation (qui est nécessaire pour les fichiers mmaped.) L'inconvénient est uniquement la perte de performances (copie de tout le contenu nécessaire), mais l'importation / exportation fonctionnera avec tous les plugins de stockage, ce qui est à mon avis beaucoup plus important.

Je pense que la meilleure solution est que kdb export et kdb import fonctionnent toujours sur des fichiers temporaires.

Je pense que les plugins devraient créer eux-mêmes le fichier temporaire, si nécessaire. De cette façon, nous évitons les pénalités de performance pour les plugins qui peuvent directement sortir vers les TTY. AFAIK mmapstorage est actuellement le seul plugin qui ne fonctionne pas avec les TTY. Nous pourrions également ajouter un test shell simple qui garantit que tous les plugins de stockage peuvent être appelés via kdb export /some/key plugin > export.file . La logique est également plus autonome, car c'est vraiment la responsabilité des plugins de savoir comment produire la sortie attendue.

Aussi pour kdb import les fichiers temporaires ne sont pas nécessaires car la lecture d'un fichier devrait toujours fonctionner, même pour les TTY (si vous disposez des autorisations appropriées).

Je pense que les plugins devraient créer eux-mêmes le fichier temporaire, si nécessaire.

Ensuite, les plugins (ou plus spécifiquement mmap) auraient besoin de savoir s'il est utilisé dans KDB ou kdb export .

@mpranj Quelle est votre opinion? Cela peut-il être corrigé dans le plugin mmap?

De cette façon, nous évitons les pénalités de performance pour les plugins qui peuvent directement sortir vers les TTY.

Dans quels cas cette pénalité de performance est-elle un problème? Peut-être dans la sauvegarde / restauration pour chaque cas de test?

AFAIK mmapstorage est actuellement le seul plugin qui ne fonctionne pas avec les TTY.

Pour l'exportation oui. Mais pour l'importation, nous avions plusieurs plugins qui ne fonctionnent pas. Si un plugin utilise fseek ou similaire, il ne peut évidemment pas fonctionner, par exemple csvstorage ou mozprefs. (le vidage devrait maintenant être corrigé)

Nous pourrions également ajouter un test de shell simple qui garantit que tous les plugins de stockage peuvent être appelés via kdb export / some / key plugin> export.file.

Vous voulez dire tests / shell / check_export.sh ligne 46?

Dans quels cas cette pénalité de performance est-elle un problème?

En fait, probablement jamais. Tant que vous utilisez les 3 versions d'argument d'exportation / importation au lieu de piping. Voir la proposition ci-dessous.

Vous voulez dire tests / shell / check_export.sh ligne 46?

Oui, mais c'est cassé, car is_not_rw_storage ne fonctionne pas. Même dump n'est pas reconnu comme un plugin de stockage.


Je pense que pour résoudre ce problème rapidement et facilement, nous devons procéder comme suit:

  1. Correction de is_not_rw_storage dans include_common.sh.in tests/shell/check_export.sh afin que nous détections des problèmes comme celui-ci à l'avenir.
  2. Dans kdb export créez un fichier temporaire, uniquement si aucun troisième argument n'est donné. Utilisez ce fichier dans les appels kdbSet et copiez ensuite son contenu dans stdout (ne devrait pas faire plus d'une ou deux lignes en C ++).
  3. De même pour kdb import créez un fichier temporaire si stdin est utilisé. Copiez tout stdin dans le fichier temporaire et utilisez ce fichier pour appeler kdbGet .
  4. Mettez à jour la documentation de kdb import et kdb export pour indiquer que le troisième argument existe. Indiquez également que si la version à deux arguments est utilisée, nous créons un fichier temporaire.

PS. Cela pourrait être good first issue

Merci d'avoir signalé que is_not_rw_storage est cassé, j'ai ouvert le # 2423

Désolé , j'étais absent pendant une semaine et je n'ai donc pas pu me renseigner.

Les messages d'erreur mmap peuvent être trompeurs. mmap() échoue avec EACCES lors de la tentative de mappage de fichiers non réguliers. À ma connaissance, cela ne fonctionnera pas sur stdout. Cela ne fonctionne pas non plus avec les tuyaux, comme indiqué dans # 2209.

Depuis POSIX:

La fonction mmap () doit être prise en charge pour les objets mémoire suivants:

  • Fichiers réguliers
  • [SHM] Objets de mémoire partagée
  • [TYM] Objets mémoire typés

En ce qui concerne les solutions dans mmapstorage, nous pouvons vérifier s'il s'agit d'un fichier régulier avec stat et ensuite:

  • écrire dans un fichier régulier temporaire, comme suggéré ci-dessus
  • écrire dans un emplacement mémoire temporaire (simplement malloc au lieu de mmap) puis copier dans le fichier non régulier (pipe, stdout, ..)

Je suis également ouvert à d'autres solutions. Les solutions ci-dessus ne changent pas beaucoup la logique de mmapstorage. Retravailler mmapstorage pour travailler directement avec des tuyaux ou des sorties standard n'a pas trop de sens pour moi.

Merci pour votre réponse!

Les messages d'erreur mmap peuvent être trompeurs.

Veuillez améliorer les messages d'erreur.

À ma connaissance, cela ne fonctionnera pas sur stdout. Cela ne fonctionne pas non plus avec les tuyaux

Veuillez ajouter ces informations aux messages d'erreur.

Les solutions ci-dessus ne changent pas beaucoup la logique de mmapstorage.

Comme votre plugin est actuellement le seul affecté, il est logique que vous fassiez la statistique et copiez tout si nécessaire. Ensuite, nous pourrions fermer ce problème sans modifications plus importantes du cadre.

Ensuite, nous pourrions fermer ce problème sans modifications plus importantes du cadre.

Nous devrions également mettre à jour les pages de manuel pour kdb import et kdb export . Actuellement, ils ne mentionnent pas les 3 versions d'argument qui ne reposent pas sur stdin / stdout.

Merci à vous deux d'avoir signalé le problème et de votre contribution!

Malheureusement, strerror imprime ces messages d'erreur trompeurs. Je peux ajouter un indice dans ce cas.

Je ferai les changements demandés dans un PR cette semaine.

Nous devrions également mettre à jour les pages de manuel pour kdb import et kdb export. Actuellement, ils ne mentionnent pas les 3 versions d'argument qui ne reposent pas sur stdin / stdout.

Peut-être n'avons-nous pas besoin de l'argument pour spécifier le fichier? L'argument entrerait en conflit une fois que kdb import/export prend en charge plusieurs plugins.

Je ferai les changements demandés dans un PR cette semaine.

Merci!

Peut-être n'avons-nous pas besoin de l'argument pour spécifier le fichier?

Ensuite, nous devons prendre en charge stdin et stdout (redirigés vers un fichier normal) dans tous les plugins. Sinon, ils ne pourront jamais être utilisés avec kdb import/export . Cela rend sens pour mmapstorage car il n'est pas portable, mais d'autres plugins portables (peut-être même lisibles par l'homme) peuvent également avoir besoin d'un fichier normal (par exemple s'ils utilisent fseek ).

L'argument entrerait en conflit une fois que kdb import/export prend en charge plusieurs plugins.

Nous pourrions facilement passer à l'utilisation des options -i FILE, --input=FILE , -o FILE, --ouput=FILE lorsque nous passerons à l'utilisation de elektraGetOpts .

Oui, nous pouvons ajouter les options -i, -o. Mais réparer les plugins (ou le framework d'import / export) pour que stdin / stdout fonctionne également serait bien dans tous les cas.

Pour résoudre ce problème avec kdb export il suffit d'implémenter la solution de contournement dans la fonction plugin-> kdbSet (). J'ai déjà mis en œuvre ceci, PR bientôt à venir.

Cela fonctionne maintenant: kdb import user/tests/ mmapstorage < test.mmap ,
mais ce n'est pas le cas: cat test.mmap | kdb import user/tests/ mmapstorage , car encore une fois mmap ne peut pas le gérer.

Pour rendre la solution cohérente (donc complètement compatible avec les fichiers non réguliers), il serait également nécessaire de la résoudre pour la fonction kdbGet (). Il existe environ trois solutions pour cela:

  1. écrire dans un fichier temporaire et le dissocier (solution un peu moche, mais simple)
  2. retravailler la moitié de mon travail mmap (moche et beaucoup de travail)
  3. faire beaucoup de copies et réimplémenter ksDeepDup pour faire des copies de méta-clés aussi (vraiment moche, code semi-simple)

Est-ce que tout cela est souhaitable ou l'ignorons-nous?

Je pense que nous pouvons l'ignorer pour le moment, car nous avons déjà quickdump. Documentez-le simplement comme n'étant pas adapté à la sérialisation. Nous allons maintenant retravailler le cadre d'import / export de toute façon, puis nous trouverons une solution appropriée. @mpranj Je vous ai

En fait, il vaut peut-être mieux que # 2639 ferme ce problème et @mpranj vous en créez un nouveau pour le problème cat ... .

2639 ferme tous les problèmes ici. Cela fonctionne bien sous Linux, j'ai juste besoin de corriger un bogue pour que cela fonctionne aussi sur les BSD.

J'avais une très bonne solution (en utilisant realpath et stat ) qui malheureusement ne fonctionnera pas sur les BSD. Cela n'a pas de sens d'y consacrer beaucoup plus de temps.

J'ai décidé de le jeter, ce qui ne rend pas mmapstorage complètement compatible avec les fichiers non réguliers. Cela ne fonctionnera qu'avec l'import / export kdb. La nouvelle solution vérifiera simplement si l'import / export kdb est utilisé, en vérifiant si le fichier est " /dev/stdin " ou " /dev/stdout ". C'est fait de la même manière dans quickdump .

J'avais une très bonne solution (utilisant realpath et stat) qui malheureusement ne fonctionnera pas sur les BSD.

C'est la solution commentée?

Cela n'a pas de sens d'y consacrer beaucoup plus de temps.

Vous avez raison, le cadre devrait gérer cela. J'ai créé le # 2640.

ne fonctionnera qu'avec l'importation / exportation kdb

Aussi avec la variante cat | kdb import ?

C'est fait de la même manière dans quickdump.

Où sont les différences?

Ce code peut-il être déplacé vers le framework d'import / export?

C'est la solution commentée?

Je l'ai laissé dans l'histoire mais j'ai supprimé les lignes plus tard. La meilleure solution à mon humble avis était jusqu'à https://github.com/ElektraInitiative/libelektra/pull/2639/commits/a523f9b38b56687d532f5101c7ef44c078e2308d. Notez que cela a bien fonctionné sous Linux mais pas BSD.

Un problème que j'ai rencontré est que stdin / stdout ne peut pas être open () ed sur les BSD. L'autre est que vous devez vraiment utiliser le realpath pour stat () le fichier et déterminer s'il s'agit d'un fichier normal. Sinon, stat n'a résolu qu'un seul niveau de liens symboliques pour moi. Cette approche a échoué sur les BSD pour moi, car realpath s'est résolu d'une manière ou d'une autre en un fichier inexistant.

Aussi avec le chat | Variante d'importation kdb?

Oui!

Où sont les différences?

La partie pertinente est la même, désolé pour la confusion. Ce que je voulais dire, c'est que nous strcmp pour / dev / stdin au lieu d'utiliser stat pour déterminer s'il s'agit d'un fichier normal. Cela signifie qu'il échouera toujours si nous utilisons / dev / fd /. Mon autre solution utilisait stat au lieu de strcmp, donc cela fonctionnait avec n'importe quel chemin.

Modifier :

Ce code peut-il être déplacé vers le framework d'import / export?

Oui, je pense que le code était presque complètement là, mais je n'ai pas eu le temps de résoudre correctement les problèmes BSD.

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

markus2330 picture markus2330  ·  3Commentaires

dominicjaeger picture dominicjaeger  ·  3Commentaires

mpranj picture mpranj  ·  3Commentaires

markus2330 picture markus2330  ·  4Commentaires

markus2330 picture markus2330  ·  4Commentaires