106 lines
3.7 KiB
Markdown
106 lines
3.7 KiB
Markdown
---
|
||
layout: post
|
||
title: Ruby File.open 'w' Acces concurrent
|
||
date: 2009-06-09
|
||
---
|
||
|
||
|
||
Je viens de tomber sur quelque chose d’étrange dans l’utilisation de l’objet [IO](http://www.ruby-doc.org/core/classes/IO.html#M002264) de [Ruby](http://ruby-lang.org) : La gestion des verrous sur les fichiers. Alors j’ai surement du rater quelque chose, mais voici mon histoire...
|
||
|
||
<pre>
|
||
{% highlight ruby %}
|
||
require 'test/unit'
|
||
|
||
DUCK="duck"
|
||
ELEPHANT="elephant"
|
||
SNAKE="snake"
|
||
FILE="test_file"
|
||
|
||
class TestFileConcurrencyAccess < Test::Unit::TestCase
|
||
def test_concurrency_access
|
||
t1 = Thread.start do
|
||
File.open(FILE, "w") do |file|
|
||
file.puts SNAKE
|
||
file.flush
|
||
sleep 8
|
||
file.puts DUCK
|
||
end
|
||
end
|
||
File.open(FILE,"r") do |f1|
|
||
assert SNAKE, f1.read
|
||
end
|
||
t2 = Thread.start do
|
||
File.open(FILE,"w") do |f|
|
||
sleep 2
|
||
f.puts ELEPHANT
|
||
end
|
||
end
|
||
t2.join
|
||
File.open(FILE,"r") do |f2|
|
||
assert ELEPHANT, f2.read
|
||
end
|
||
|
||
t1.join
|
||
File.open(FILE,"r") do |f3|
|
||
assert SNAKE, f3.readline
|
||
assert DUCK, f3.readline
|
||
end
|
||
|
||
end
|
||
end
|
||
{% endhighlight %}
|
||
</pre>
|
||
|
||
[fichier source](/files/test_file_concurrency_access.rb)
|
||
|
||
Le resultat d’execution de ce test donne une erreur sur la dernière lecture:
|
||
|
||
<pre>
|
||
{% highlight bash %}
|
||
Loaded suite test_file_concurrency_access
|
||
|
||
Started
|
||
E
|
||
|
||
Finished in 8.003509 seconds.
|
||
1) Error:
|
||
test_concurrency_access(TestFileConcurrencyAccess):
|
||
EOFError: end of file reached
|
||
test_file_concurrency_access.rb:38:in `readline’
|
||
test_file_concurrency_access.rb:38:in `test_concurrency_access’
|
||
test_file_concurrency_access.rb:36:in `open’
|
||
test_file_concurrency_access.rb:36:in `test_concurrency_access’
|
||
|
||
1 tests, 3 assertions, 0 failures, 1 errors
|
||
{% endhighlight %}
|
||
</pre>
|
||
|
||
Mais ce qui me gène (et qui ne ressort pas dans mon test, je l’avoue) c’est que j’aurais pensé que le deuxième *File.open* ne puisse pas s’executé, et me renvoie une Error du type: *“Le fichier est déjà ouvert en écriture par quelqu’un d’autres”*... Mais non, et du coup, j’ai un fichier assez moche qui ne ressemble à rien:
|
||
|
||
<pre>
|
||
elephduck
|
||
</pre>
|
||
|
||
Alors qu’on pourrait penser obtenir un truc dans le genre:
|
||
|
||
<pre>
|
||
snake
|
||
duck
|
||
</pre>
|
||
|
||
Avec éventuellement une erreur sur l’écriture d’éléphant dans le fichier.
|
||
|
||
J’ai également fait un essai en utilisant le code contenu dans chaque thread pour les executer dans deux console différentes, j’arrive au même résultat (c’est du coup dans test/unit, mais au niveau du contenu de <span class="caps">FILE</span> à la fin, j’ai là même chose...)
|
||
[Fichier write_quickly.rb pour l’écriture d’ELEPHANT](http://zone.elsif.fr/write_quickly.rb)
|
||
[Fichier write_slowly.rb pour l’écriture de SNAKE et DUCK](http://zone.elsif.fr/write_slowly.rb)
|
||
|
||
Bref, je suis perplexe. J’avoue ne pas avoir envie d’envoyer cela sur la [mailing-liste Ruby-talk](http://www.ruby-lang.org/fr/community/mailing-lists/), ni sur celle de [JRuby](http://jruby.org) d’ailleurs (car j’ai vérifier, j’ai le même problème en JRuby). Du moins tant que je n’ai pas creusé un peu plus.
|
||
|
||
J’ai sûrement du faire une erreur quelque part, oublier quelque chose, ou faire quelque chose de travers. **Si quelqu’un lit cela et à une idée, merci d’en m’en parler, je suis preneur !**.
|
||
|
||
Si c’est un comportement souhaité, j’aimerais comprendre pourquoi, et si c’est un oubli ou une erreur, j’aimerais bien aider à trouver une solution.
|
||
|
||
*ps: Retour au thème Scribbish que je trouve plus lisible, en attendant que je refasse quelque chose...*
|
||
|
||
|