martes, 22 de junio de 2010

Sandbox de codigo ruby (remake 2010)



Anteriormente en este mismo blog anuncie la creacion de un sandbox para ruby. Ese proyecto se cancelo y quedo definitivamente incompleto. El proyecto se llamaba arena-ruby-sandbox.

Hace un tiempo comenze el desarrollo de un nuevo sandbox (llamado shikashi), pero con un diseño y una idea totalmente distinta: mientras arena-ruby-sandbox es un intento de sandbox en codigo ruby puro, shikashi se implementa utilizando una modificacion al interprete de ruby hecha en C en formato de extension (llamada rallhook).

Funciona mejor que su antecesor ademas de permitir usar casi todos los elementos del lenguaje como clases y metodos singleton cosa que arena-ruby-sandbox no permitia.

Recientemente libere la version 0.7.1 de rallhook ademas de la version 0.1.0 del sandbox shikashi. La documentacion del gem (que incluye instrucciones de como instalarlo, ejemplos de uso y descripcion completa del API) esta en http://tario.github.com/shikashi/doc/

NOTA: tambien se puede instalar haciendo

gem install shikashi

Cosa que no menciona el README y lo actualizare en proximos releases.

sábado, 19 de junio de 2010

Post-mortem debugging en linux


Que es el debugging post-mortem

El debugging post-mortem es una clasica tecnica de debugging que consiste en que el sistema operativo genera un volcado completo de los registros, los threads y la memoria de un proceso que termina de manera anomala (ya sea por SIGSEGV o por SIGABRT), en linux estos volcados se llaman "cores" y se pueden examinar con gdb para ver en que punto del codigo ocurrio el error, los threads con sus backtraces, los registros, e incluso el valor de las variables (si se tiene informacion de debug) en el momento en que termino el proceso.

Como activarlo

Por default, en la mayoria de los sistemas linux viene desactivado, pero activarlo es tan simple como ejecutar en la terminal:

ulimit -c 4000000000

Que determina que el limite maximo para el tamaño del core sera de aproximadamente 4Gb (valores mucho mayores pueden ser rechazados a no ser que se tenga privilegios de root).

Esto solo tiene validez en la shell en la que se activo, si se necesita que este siempre activo para cualquier sesion, se podria agregar la linea "ulimit -c 4000000000" al final del archivo ~/.bashrc

echo ulimit -c 4000000000 >> ~/.bashrc

Como verlo funcionando

Se crea un programa de purebas, "mytest.c" que genera un error abort()

#include "stdlib.h"

int main() {
abort();
}


Se compila generando informacion de debug y se ejecuta:

gcc -ggdb mytest.c -o mytest
./mytest

El programa falla y seguramente anunciara que se genero el core (en mi caso solamente el archivo generado se llama "core", en algunos sistemas pone el pid o cosas asi)

Se puede usar gdb para analizar el core, tambien hay que pasarle como parametro el ejecutable que genero el core para poder ver la informacion de debug:

gdb -c core mytest


A partir de entonces se puede examinar el estado que tenia el programa en el momento de finalizar como si se tratara de un debug normal:

(gdb) bt
#0 0x00007f55e7ef3a75 in raise () from /lib/libc.so.6
#1 0x00007f55e7ef75c0 in abort () from /lib/libc.so.6
#2 0x000000000040052d in main () at mytest.c:4
(gdb) info threads
* 1 Thread 4352 0x00007f55e7ef3a75 in raise () from /lib/libc.so.6
(gdb) disass main
Dump of assembler code for function main:
0x0000000000400524 <+0>: push %rbp
0x0000000000400525 <+1>: mov %rsp,%rbp
0x0000000000400528 <+4>: callq 0x400418
End of assembler dump.
(gdb) print/x $rcx
$4 = 0xffffffffffffffff
(gdb)

viernes, 18 de junio de 2010

Deshacer el push en git

Actualizacion: Quick fix

Alguien pusheo commits que no debia, o por alguna razon se pretende "deshacer" commits que ya se enviaron al servidor central.

Quick fix

Buscar el commit a donde se pretende volver: (usar git log o git reflog, etc...), y despues hay que ejecutar estos commandos (donde a_donde_volver se reemplaza por el commit):


git reset a_donde_volver
git checkout HEAD .
git push --force


Y a trabajar

NOTA: usar --force solo para casos especificos como este, ya que directamente sobreescribe cambios en la rama remota (que es lo que se pretende hacer en este caso)

Narrado (for dummys)

Todo lo que voy a explicar es asumiendo que se esta trabajando en la rama master (que es la default en git), si no estas trabajando en la rama master, el comando "git branch" muestra la rama de trabajo en la que estas trabajando

Antes, que nada, se puede hacer un tag del master actual:

git tag ultimo_master master


Posteriormente, hay que encontrar el commit al cual se quiere volver, se pueden revisar los logs (el nombre de la rama es opcional, si no se indica usa la rama de trabajo actual):

git log [master]


Supongamos que el commit al que se quiere volver es 0123456789abcd..., puede ser util taguearlo para referenciaro facilmente mas adelante (aunque se puede hacer todo referenciando al commit, directamente)


git tag a_donde_volver 0123456789abcd...


Posteriormente, se hace un reset a para que la rama master local referencie a ese commit, y despues un checkout para cambiar los archivos y que coincidan


git reset a_donde_volver
git checkout HEAD .


Despues, hay que sobreescribir la referencia master remota con la actual, pero hay que usar --force para que git no verifique si se trata de un fast-forward (porque sino rechaza la operacion), recordar usar --force solamente en casos especificos como este.


git push --force


Y despues se puede seguir trabajando normalmente

Bonus track

Puede ser util crear un branch en el servidor a partir del master original antes de que se revierta (para poder analizarlo entre todos, etc...), para hacer esto:


git push origin ultimo_master:refs/heads/old_master


Y en este post explico como usar los branches:

http://nilclass.blogspot.com/2009/08/branches-remotos-en-git.html

miércoles, 16 de junio de 2010

Solucion a sectores dañados en linux. EXT2 y EXT3

Sintomas

El sistema se cuelga en tareas estupidas como reproducir una pelicula, instalar paquetes, configurar cosas, abrir determinados archivos para despues de un tiempo de estar "colgado" anunciar que hasta la tarea mas simple fallo por un "I/O error".

Hace falta confirmarlo tambien con los logs, la informacion necesaria aparece en el syslog (en /var/log/syslog ), se encontraran lineas similares a estas:


Jun 16 16:17:56 ubuntu kernel: [ 6193.840250] Buffer I/O error on device sda1, logical block 155153547
Jun 16 16:17:56 ubuntu kernel: [ 6193.840254] Buffer I/O error on device sda1, logical block 155153548
Jun 16 16:17:56 ubuntu kernel: [ 6193.840258] Buffer I/O error on device sda1, logical block 155153549


O tambien de estas:

Jun 15 20:16:01 ubuntu kernel: [ 25.636424] ata1.00: status: { DRDY ERR }
Jun 15 20:16:01 ubuntu kernel: [ 25.640935] ata1.00: configured for UDMA/133
Jun 15 20:16:01 ubuntu kernel: [ 25.640951] ata1: EH complete
Jun 15 20:16:01 ubuntu kernel: [ 29.172011] ata1.00: exception Emask 0x0 SAct 0x7fff SErr 0x0 action 0x0
Jun 15 20:16:01 ubuntu kernel: [ 29.172013] ata1.00: irq_stat 0x40000008
Jun 15 20:16:01 ubuntu kernel: [ 29.172016] ata1.00: failed command: READ FPDMA QUEUED
Jun 15 20:16:01 ubuntu kernel: [ 29.172022] ata1.00: cmd 60/08:28:a7:74:3f/00:00:09:00:00/40 tag 5 ncq 4096 in
Jun 15 20:16:01 ubuntu kernel: [ 29.172025] ata1.00: status: { DRDY ERR }
Jun 15 20:16:01 ubuntu kernel: [ 29.176722] ata1.00: configured for UDMA/133
Jun 15 20:16:01 ubuntu kernel: [ 29.176740] ata1: EH complete
Jun 15 20:16:01 ubuntu kernel: [ 32.440790] ata1.00: exception Emask 0x0 SAct 0x7fab SErr 0x0 action 0x0
Jun 15 20:16:01 ubuntu kernel: [ 32.440792] ata1.00: irq_stat 0x40000008
Jun 15 20:16:01 ubuntu kernel: [ 32.440795] ata1.00: failed command: READ FPDMA QUEUED
Jun 15 20:16:01 ubuntu kernel: [ 32.440801] ata1.00: cmd 60/08:48:a7:74:3f/00:00:09:00:00/40 tag 9 ncq 4096 in
Jun 15 20:16:01 ubuntu kernel: [ 32.440805] ata1.00: status: { DRDY ERR }
Jun 15 20:16:01 ubuntu kernel: [ 32.440807] ata1.00: error: { UNC }
Jun 15 20:16:01 ubuntu kernel: [ 32.445770] ata1.00: configured for UDMA/133
Jun 15 20:16:01 ubuntu kernel: [ 32.445785] ata1: EH complete


Solucion

Si algunos sectores del disco estan dañados sera inevitable que se pierda el disco entero tarde o temprano, por eso lo primero que se debe hacer es backup de toda la informacion.
Posteriormente, para poder seguir usando el disco, se debe hacer una revision completa marcando los bloques dañados como tal, el comando que hay que ejecutar es:


e2fsck -c /dev/sda1


Reemplazando /dev/sda1 por la particion que tengan que reparar.

Esto solo se puede hacer con la particion desmontada, para poder hacerlo asi recomiendo una de tres opciones:

1) Usar un live-cd como los de ubuntu, que les permite acceder a las particiones, tienen los comandos basicos y hasta entorno grafico para que puedan, por ej, escribir articulos en su blog publicando la solucion (es mi caso)

2) Usar una opcion de "rescue" (no estoy seguro si viene con ubuntu, pero viene con todos los fedora) eso les da una shell con privilegios de root pero nada de graficos, de ventanitas de gelatina, ni menos cubos de escritorio girando

3) Inician el sistema normalmente, y con Ctrl+Alt+F1 pasan a la consola sin graficos, ejecutan:


sudo init 1


Para pasar a runlevel 1 que detiene todos los servicios (incluyendo el entorno grafico) y permite desmontar cualquier particion, ahi ejecutan el escaneo y cuando termine vuelven a montar la particion y hacen


sudo init 5


Para volver a runlevel 5

Esta ultima es mas para "hackers" pero es innecesariamente complicada y me fracture el dedo indice cuando quise hacerla.

domingo, 13 de junio de 2010

Renovado diseño del blog

Tarde de domingo sin saber que hacer, renovacion visual del blog. Se hicieron los siguientes cambios.

* Se cambiaron los colores blancos, claros de blogs de psicologia newbies por colores darks, bizarros propios del underground, el H4X0R1NG, el KRAK0RING y PRHEKIRING aunque el blog NO PUBLICARA ARTICULOS DE ESA CATEGORIA :P (para eso hay blogs muy buenos en la web)

* Se cambiaron los colores del syntax highlighting en el style para que tenga sentido con los nuevos colores (todo dark) y se incluyo el style como tag en el template del blog para acelerar la carga de la pagina

* Se incluyeron todos los Javascripts de highlighting en el template del blog (en los tags ) en lugar de que sean referencia remota al sitio donde estaban alojados, con esto se acelera por mucho la carga de la pagina.

* Se cambio el fondo por uno de esos fondos "geeks" que hay en las opciones, pero como esto es ruby, se pinto de rojo (el original era azul)

Lo que mas me ayudo fue el plugin firebug para probar como quedan los colores antes de grabar en el template, y analizar un poco el source code de la pagina.
Tambien me sirvio bastante el irb para escapear el javascript, la libreria CGI:


require "cgi"
CGI.escapeHTML("<script>alert('hello world')</script>");
# => "&lt;script&gt;alert('hello world')&lt;/script&gt;"


Espero que la experiencia blogger sea mas ruby ahora