Re: Mixins

Exacto, yo también pensé que era mongrel pero no. Cuando quito los
include
de ambas clases (Integer y Float) mongrel inicia correctamente.

También lo he probado con webrick y nada.

No sé, pienso que en Rails hay que hacer algo para incluir módulos en
ciertas clases “base”??

– fxn

On Jan 2, 2008, at 5:00 PM, edgar.js wrote:

Exacto, yo también pensé que era mongrel pero no. Cuando quito los
include de ambas clases (Integer y Float) mongrel inicia
correctamente.

También lo he probado con webrick y nada.

Quieres decir que arranca bien o que peta igual?

No sé, pienso que en Rails hay que hacer algo para incluir módulos
en ciertas clases “base”??

No me consta, en principio uno puede abrir cualquier clase donde
quiera. Todo corre en un mismo interprete y solo ha de cumplirse que
el codigo que vaya a usarlo se ejecute despues del que define la
extension. Por eso es costumbre poner esas cosas al final de
environment.rb o en los initializers de la 2.

Es muy raro, pareceria claro que petara porque no se encuentra algo
definido en tu extension, pero el problema es que no se carga un
archivo de la distribucion de Mongrel!

Rails hace lo mismo que tu en Active Support:

class Integer #:nodoc:
include ActiveSupport::CoreExtensions::Integer::EvenOdd
include ActiveSupport::CoreExtensions::Integer::Inflections
end

Pero vaya seguro que no te estoy contando nada que no supieras. Es
mosqueante el comportamiento, puedes por favor responder con lo de
webrick arriba (con traza si peta) y pasar el enlace al plugin que no
lo encuentro (y lo tuve porque recuerdo haber visto el init.rb).
Podrias decir en que fichero reabres Integer?

– fxn

Trataré de ordernar un poco.

Mongrel:
No puede iniciar el servidor, y sale este error:
Parked at Loopia (es diferente al anterior [
Parked at Loopia ], ahora estoy en otra máquina. Pero
tomemos en cuenta este último [134027] ya que como dices, es más
probable que la otra sea un error del mongrel.)

Webrick:
Inicia el servidor, pero cuando intento navegar a la aplicación
(localhost:3000) sale este error: Parked at Loopia

El código está en http://svn.mimbles.net/rails/plugins/readable_numbers
y todo el contenido está en el fichero lib/readable_numbers.rb (ahi
mismo reabro las clases Float e Integer). Puedes correr el test y
observarás que ahi corre correctamente.

On Jan 2, 2008, at 6:37 PM, Edgar j. Suarez wrote:

El código está en http://svn.mimbles.net/rails/plugins/
readable_numbers
y todo el contenido está en el fichero lib/readable_numbers.rb (ahi
mismo reabro las clases Float e Integer). Puedes correr el test y
observarás que ahi corre correctamente.

El problema definitivamente no es de Rails ni Mongrel, a Ruby o a Time
parece que no le mola que escribas Integer#to_str. Lo que no llego a
ver es si es un bug o es que se esta violando algo.

Mira, la linea donde specification.rb peta tiene una llamada a
Time.local. Si escribimos este magnifico foo.rb

class Integer
  def to_str
    "foo"
  end
end

que es analogo a lo que hace el plugin a efectos de depurar esto y
lanzamos un irb pelado:

$ irb
irb(main):001:0> Time.local(2008, 1, 3)
=> Thu Jan 03 00:00:00 +0100 2008
irb(main):002:0> require 'foo'
=> true
irb(main):003:0> Time.local(2008, 1, 3)
(irb):3: [BUG] Bus Error
ruby 1.8.6 (2007-09-24) [i686-darwin9.1.0]

zsh: abort      irb

Esto lo he traceado desde time.c y el punto exacto donde peta es la
llamada a

RSTRING(v[1])->ptr

de la linea 352, y sospecho que tiene que ver con poco antes se ha hecho

VALUE s = rb_check_string_type(v[1]);

y la existencia de to_str (usada siguiendo la traza por
rb_check_string_type) ha liado algo que ya no he terminado mas de ver.
v[1] juega el papel del mes ahi, y Time.local acepta cadenas
perfectamente, y si le pasamos “foo” literal en la llamada da una
excepcion controlada conforme el parametro esta mal:

irb(main):001:0> Time.local(2008, "foo", 1)
ArgumentError: argument out of range

from (irb):1:in local' from (irb):1 irb(main):002:0> Time.local(2008, "foobarbaz", 1) ArgumentError: argument out of range from (irb):2:in local’
from (irb):2
from :0

Asi que ahi hay alguna combinacion lineal ahi fatal. No se decir si es
cosa nuestra o un bug.

Se entiende que solo objetos que son intercambiables y actuan
verdaderamente como cadenas deben responder a to_str, pero esa regla
es muy ambigua. El Pickaxe por ejemplo dice que no deberia
implementarse para una clase que representa numeros romanos (pagina
356), pero entiendo que es como algo conceptual. Exception implementa
to_str, si pasamos Excepcion como mes hay un error controlado tambien
en lugar de un bus error:

irb(main):001:0> Time.local(2008, Exception, 1)
TypeError: can't convert Class into Integer

from (irb):1:in `local’
from (irb):1

Formalmente no se que implicaciones tiene to_str que uno pueda violar.
Una cosa es que conceptualmente puedas ver a la clase X como String e
implementar X#to_str en consecuencia, y otra es que implementes
X#to_str de un modo que formalemente sea invalido. Si hay tal cosa la
desconozco.

Es verdad que los Fixnums son tipos especiales en el interprete y
puede que tenga relacion, pero estamos igual, faltaria determinar si
es un bug o un mal uso de to_str. Al fin y al cabo a Integer le
enchufamos de todo sin problema.

– fxn

Hmm, muy interesante. No pensé que eso fuera a ser la causa del error.

En ese caso bastaría con renombrar el método, lo cual ya he probado y si
funciona.

Te agradezco mucho Xavier, en verdad se aprecia tu ayuda.

Por ejemplo el código siguiente: (mktime y local da igual, he estado
probando con mktime así que lo dejo, sorry).

Time.mktime(2,2) => No peta
Time.mktime(2,“feb”) => Tampoco peta
Time.mktime(2,‘2’) => No peta
Time.mktime(2,“Febrero”) => PETA, se esperan 3 caracteres
correspondientes
al mes.
Time.mktime(2,“xxx”) => No le gusta el porno así que vuelve a petar. xxx
no
es un mes válido.

class Mes
def to_s
“feb”
end
def to_i
2
end
end

Time.mktime(2,Mes.new) => Peta. Quiere String o Integer, pero no cosas
raras.
Time.mktime(2,Mes.new.to_i) = Funciona
Time.mktime(2,Mes.new.to_s) = Funciona

class Mes
def to_str
to_s
end
end

Time.mktime(2,Mes.new.to_i) => Funciona
Time.mktime(2,Mes.new.to_s) => Funciona
Time.mktime(2,Mes.new) => Se arma la gorda. Crees que es Mes es un
String
(inocente…), y claro empieza a tocar las cosas internas de Mes como si
este fuese un String.

A fines prácticos, da igual que fuese una clase Mes o una clase Integer,
ya
que lo primero que comprueba es si es un String, viendo si existen el
atributo to_str.

¿Por qué pasa esto?

El problema está como dices en la linea 352, cuando dice.

strcasecmp(months[i], RSTRING(v[1])->ptr) == 0) {

RSTRING(v[1])->ptr
que significa
struct RString v[1]->ptr

Estaríamos intentando meter por moldeado un (lo que sea que responde a
to_str) en un molde para RString.

Obviamente nuestro Objeto, no tiene el puntero ptr (a la cadena de
caracteres), o si lo tiene, igual no lo tiene en la misma posición y ni
el
mismo contenido. Que pasa, que vete tu a saber a que cacho de memoria le
habrá mandando vete tu a saber que puntero.

Si seguimos investigando, la función de time.c time_arg, hará esto, por
que
piensa que le estamos pasando un string… ¿Pero por que piensa eso? Ahí
tenemos que irnos a rb_check_string_type, definida en string.c. Esta
función
devuelve NIL o NULL, en caso de que no sea un string. Esta función llama
a
la genérica (Que putada el DRY en estos momentos coño)
rb_check_conver_type(str, T_STRING, “String”, “to_str”);

Ahora bien sigues bajando el nivel y llegas hasta rb_obj_respond_to (en
eval.c) , y por lo que veo se queda en que si responde a to_str es una
string.

Aquí el bug ( A mi juicio en toda regla), está donde indicas, ya que se
comprueba que responde a str, pero no se afirma que es una STRING.

Es decir, que ruby alegremente piensa que todo lo que responde a to_str
es
un string.

Ahora ya entra los patrones que se hayan seguido de diseño para saber
donde
está el error, y la verdad es la primera vez que miro el código de ruby
y de
un lenguaje de programación así que paso de intentar hacer un parche,
por
que no sabría donde parchear.

Puede pasar dos cosas:

a) La implementación de time_arg está incorrecta. En este caso, se
interpreta que rb_check_string_type, indica si es capaz de responder a
to_str y no indica que es un String.

b)La implementación de rb_check_string_type es incorrecta, ya que solo
chequea si responde a to_str.

c)Somos unos bocazas y to_str es un palabro reservado solo para strings.

Así que si hay alguien que sepa algo más al respecto, que se plantee
hacer
un patch de verdad.

Notas: He estado usando los sources de ruby-1.8.6

Como dices, yo también trabajo con Ruby 1.8.6 y supongo que Xavier
también. No sé si esto ya esté arreglado en la versión 1.9, de lo
contrario sería bueno levantar un ticket no creen? Al final, si resulta
que no es un bug… no lo corregirán y punto. jeje.

Aunque, eso se los dejo a ustedes (si es que no les molesta), la verdad
yo nunca he levantado un ticket y no sé cómo se haga.

Saludos.

On Jan 4, 2008, at 5:29 AM, Edgar J. Suarez wrote:

Como dices, yo también trabajo con Ruby 1.8.6 y supongo que Xavier
también. No sé si esto ya esté arreglado en la versión 1.9, de lo
contrario sería bueno levantar un ticket no creen? Al final, si
resulta
que no es un bug… no lo corregirán y punto. jeje.

Aunque, eso se los dejo a ustedes (si es que no les molesta), la
verdad
yo nunca he levantado un ticket y no sé cómo se haga.

Yo creo que hay un bug de Ruby por ahi, si tengo tiempo mirare de
llegar un poco mas al tema y preguntar/reportar en core. Buen analisis
Guillermo!

Dicen que si implementas to_str tu objeto debe ser intercambiable con
Strings, por ejemplo es concatenable automaticamente. Aun y en el caso
de que no fuera legal ese to_str pelado (que yo creo que no debe ser
porque Exception la veo analoga) saltaria una excepcion controlada. Un
bus error, al margen del uso correcto o incorrecto de to_str, indica
un bug del interprete por si solo.

Pero me da a mi que como el mes acepta tanto enteros como cadenas
tiene algo en algun punto que se hace un lio al recibir un entero que
tiene to_str.

– fxn

On 1/4/08, Xavier N. [email protected] wrote:

Pero me da a mi que como el mes acepta tanto enteros como cadenas
tiene algo en algun punto que se hace un lio al recibir un entero que
tiene to_str.

Se ve claramente el bug. Si tiene to_str, asume que es una estructura C
de
tipo RString. Intenta acceder a uno de sus miembros (ptr), y ese miembro
no
existe ni en Integer, ni en ninguna otra clase. Por lo tanto se
generaría la
típica NULLPOINTEREXCEPTION de java, o un core en cualquier programa. No
te
compliques, por que no hay más complicación.
Informame si has mandado el bug, por que si no ya me busco yo las
castañas
para enviarlo. Por que independientemente de las acepciones, algo que
genera
un core es un BUG, de todas todas. Si miras el signal.c el mismo asume
que
es un bug.

static RETSIGTYPE
sigbus(sig)
int sig;
{
#if defined(HAVE_NATIVETHREAD) && defined(HAVE_NATIVETHREAD_KILL)
if (!is_ruby_native_thread() && !rb_trap_accept_nativethreads[sig])
{
sigsend_to_ruby_thread(sig);
return;
}
#endif

rb_bug("Bus Error");

}

Dejo el backtrace.

(gdb) backtrace
#0 0x001579c4 in rb_time_timeval ()
#1 0x000e8cfc in rb_block_proc ()
#2 0x000e9998 in rb_block_proc ()
#3 0x000e68ec in rb_block_proc ()
#4 0x000f6ad8 in rb_load_protect ()
#5 0x000f6b20 in ruby_exec ()
#6 0x000f6b68 in ruby_run ()
#7 0x00001fb0 in main ()

Un Saludo

On Jan 4, 2008, at 12:12 PM, Guillermo wrote:

Se ve claramente el bug. Si tiene to_str, asume que es una
estructura C de tipo RString. Intenta acceder a uno de sus miembros
(ptr), y ese miembro no existe ni en Integer, ni en ninguna otra
clase. Por lo tanto se generaría la típica NULLPOINTEREXCEPTION de
java, o un core en cualquier programa. No te compliques, por que no
hay más complicación.

Seguro que es solo eso? Vull dir, esta claro que termina pensando que
tiene estructura de string. Pero por que no peta con Exception si el
problema es solo el to_str?

$ irb
irb(main):001:0> Time.local(2008, Exception.new, 1)
ArgumentError: argument out of range

from (irb):1:in `local’
from (irb):1

Yo me huelo que hay algo mas.

Informame si has mandado el bug, por que si no ya me busco yo las
castañas para enviarlo. Por que independientemente de las
acepciones, algo que genera un core es un BUG, de todas todas. Si
miras el signal.c el mismo asume que es un bug.

Seguro seguro, en ningun caso deberia comportarse de ese modo.

Dale candela al reporte!

– fxn

He escrito a la lista de ruby-devel, a ver que dicen.
Perdón a la lista por el OT.

On 1/4/08, Xavier N. [email protected] wrote:

Seguro que es solo eso? Vull dir, esta claro que termina pensando que
tiene estructura de string. Pero por que no peta con Exception si el
problema es solo el to_str?

Se te olvida una linea
if (RSTRING_LEN(s) == 3 &&

to_str de Exception, devuelve una cadena de más de tres caracteres
(supuestamente para “Jan”, “Feb”,…), intenta acceder a ptr de
Exception,
y tenemos Bus Error, o cagada de punteros.

Si sobrecargas Exception, pasa igual:

class Exception
def to_str
“foo”
end
end
=> nil
a = Exception.new
=> #<Exception: Exception>
a.to_str
=> “foo”
Time.mktime(2,a)
(irb):9: [BUG] Bus Error
ruby 1.8.6 (2007-06-07) [universal-darwin9.0]

Abort trap

y como curisoidad, en ruby 1.9, si es tu propia clase, no peta, pero si
es
una predefinida (ahí todavía no he llegado, sí).

Dump de ruby 1.9 con símbolos de depurado:

Kakafuti2:ruby-1.8.6 guillermo$ irb
irb(main):001:0> class Exception
irb(main):002:1> def to_str
irb(main):003:2> “foo”
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> Time.mktime(2,Exception.new)
(irb):6: [BUG] Bus Error
ruby 1.9.0 (2007-12-25 revision 14709) [powerpc-darwin9.1.0]

– control frame ----------
c:0024 p:---- s:0074 b:0074 l:000073 d:000073 CFUNC :mktime
c:0023 p:0028 s:0069 b:0069 l:0026a4 d:000068 EVAL (irb):6
c:0022 p:---- s:0068 b:0068 l:000067 d:000067 FINISH :empty?
c:0021 p:---- s:0066 b:0066 l:000065 d:000065 CFUNC :eval
c:0020 p:0023 s:0059 b:0059 l:000058 d:000058 METHOD
/tmp/ruby1.9/lib/ruby/1.9.0/irb/workspace.rb:81
c:0019 p:0025 s:0052 b:0051 l:000050 d:000050 METHOD
/tmp/ruby1.9/lib/ruby/1.9.0/irb/context.rb:219
c:0018 p:0024 s:0046 b:0046 l:001cd4 d:000045 BLOCK
/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:150
c:0017 p:0024 s:0040 b:0040 l:000039 d:000039 METHOD
/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:259
c:0016 p:0009 s:0035 b:0035 l:001cd4 d:000034 BLOCK
/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:147
c:0015 p:0091 s:0032 b:0032 l:000021 d:000031 BLOCK
/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:244
c:0014 p:---- s:0032 b:0032 l:000031 d:000031 FINISH :block_given?
c:0013 p:---- s:0030 b:0030 l:000029 d:000029 CFUNC :loop
c:0012 p:0007 s:0027 b:0027 l:000021 d:000026 BLOCK
/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:231
c:0011 p:---- s:0028 b:0028 l:000027 d:000027 FINISH :each
c:0010 p:---- s:0026 b:0026 l:000025 d:000025 CFUNC :catch
c:0009 p:0017 s:0022 b:0022 l:000021 d:000021 METHOD
/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:230
c:0008 p:0034 s:0019 b:0019 l:001cd4 d:001cd4 METHOD
/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:146
c:0007 p:0009 s:0016 b:0016 l:00140c d:000015 BLOCK
/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:70
c:0006 p:---- s:0017 b:0017 l:000016 d:000016 FINISH :(null)
c:0005 p:---- s:0015 b:0015 l:000014 d:000014 CFUNC :catch
c:0004 p:0152 s:0011 b:0011 l:00140c d:00140c METHOD
/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:69
c:0003 p:0033 s:0006 b:0006 l:000005 d:000005 TOP
/tmp/ruby1.9/bin/irb:13
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH :inherited
c:0001 p:0000 s:0002 b:0002 l:000001 d:000001 TOP :26

DBG> : “(irb):6:in irb_binding'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb/workspace.rb:81:in eval’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb/workspace.rb:81:in evaluate'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb/context.rb:219:in evaluate’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:150:in block (2 levels) in eval_input'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:259:in signal_status’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:147:in block in eval_input'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:244:in block (2
levels)
in each_top_level_statement’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:231:in loop'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:231:in block in
each_top_level_statement’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:230:in catch'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb/ruby-lex.rb:230:in each_top_level_statement’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:146:in eval_input'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:70:in block in start’”
DBG> : “/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:69:in catch'" DBG> : "/tmp/ruby1.9/lib/ruby/1.9.0/irb.rb:69:in start’”
DBG> : “/tmp/ruby1.9/bin/irb:13:in `'”
– backtrace of native function call (Use addr2line) –
0xd9508
0x1c11c
0x1c188
0x9bc04
0x95f30bb4

Abort trap
Kakafuti2:ruby-1.8.6 guillermo$

Un Saludo y suerte con los Reyes :stuck_out_tongue:

On Jan 4, 2008, at 2:39 PM, Guillermo wrote:

He escrito a la lista de ruby-devel, a ver que dicen.

Para cerrar el thread, confirmado y arreglado:

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/14766

Bien!

– fxn