Folclore de programadores e ingenieros (parte 2)



Continuación de la colección de historias de Internet sobre cómo los bichos a veces tienen manifestaciones completamente increíbles. La primera parte está aquí .



Mas magia



Hace unos años, rebusqué en los armarios que albergaban una computadora PDP-10 que pertenecía al laboratorio de inteligencia artificial del MIT. Noté un pequeño interruptor pegado al marco de uno de los gabinetes. Estaba claro que se trataba de un producto casero, añadido por uno de los artesanos del laboratorio (nadie sabía quién exactamente).



No tocará un interruptor desconocido en su computadora sin saber lo que hace, porque podría romper su computadora. El cambio fue firmado de forma completamente ininteligible. Tenía dos posiciones, y las palabras "magia" y "más magia" estaban escritas a lápiz en el cuerpo metálico. El interruptor estaba en la posición más mágica. Llamé a uno de los técnicos para que echara un vistazo. Nunca antes había visto algo así. Tras una inspección más cercana, resultó que solo un cable va al interruptor. El otro extremo del cable desapareció en el revoltijo de cables dentro de la computadora, pero la naturaleza de la electricidad dicta que un interruptor no hará nada hasta que conecte dos cables.



Era obvio que se trataba de una broma estúpida de alguien. Después de asegurarnos de que el interruptor no hace nada, lo cambiamos. La computadora se desmayó inmediatamente.



Imagínense nuestro asombro. Lo atribuimos a una coincidencia, pero aún así volvimos a colocar el botón en la posición "más mágica" antes de iniciar la computadora.



Un año después, le conté esta historia a otro técnico, David Moon, hasta donde puedo recordar. Cuestionó mi idoneidad, o sospechó que creía en la naturaleza sobrenatural de ese interruptor, o pensó que estaba jugando con su falsa historia. Para probar mi punto, le mostré este interruptor, todavía pegado al marco y con un solo cable, todavía en la posición "más mágica". Examinamos el interruptor y el cable de cerca y descubrimos que estaba conectado a tierra. Parecía doblemente sin sentido: el interruptor no solo no funcionaba eléctricamente, sino que también estaba enchufado en un lugar que no afectaba nada. Lo movimos a una posición diferente.



La computadora se quedó en blanco inmediatamente.



Nos comunicamos con Richard Greenblatt, que era un técnico de mucho tiempo en el MIT, que estaba cerca. Él también nunca había visto el interruptor. Lo examiné, llegué a la conclusión de que el interruptor era inútil, saqué los cortadores de alambre y corté el cable. Luego encendimos la computadora y comenzó a funcionar silenciosamente.



Todavía no sabemos cómo este interruptor apagó la computadora. Existe la hipótesis de que se produjo un pequeño cortocircuito cerca del contacto a tierra, y la traslación de las posiciones del interruptor cambió la capacitancia eléctrica de modo que el circuito se interrumpió cuando pasaron pulsos con una duración de una millonésima de segundo a través de él. Pero no lo sabremos con seguridad. Solo podemos decir que el cambio fue mágico.



Todavía está en mi sótano. Probablemente sea una tontería, pero normalmente lo mantengo en la posición "más mágica".



En 1994, se propuso otra explicación para esta historia. Tenga en cuenta que el cuerpo del interruptor era de metal. Suponga que se conecta un contacto sin un segundo cable al cuerpo (generalmente el cuerpo está conectado a tierra, pero hay excepciones). El cuerpo del interruptor estaba conectado a la caja de la computadora, que probablemente estaba conectada a tierra. Entonces, el circuito de tierra dentro de la máquina puede tener un potencial diferente al del circuito de tierra del marco, y cambiar la posición del interruptor provocó una caída o aumento de voltaje, y la máquina se reinició. Este efecto probablemente fue descubierto por alguien que conocía la diferencia de potencial y decidió hacer un cambio de broma.



OpenOffice no imprime los martes



Hoy en el blog encontré una mención de un error interesante. Algunas personas tenían problemas para imprimir documentos. Más tarde, alguien notó que su esposa se quejaba de no poder imprimir los martes.



En los informes de errores, algunos inicialmente se quejaron de que debía ser un error de OpenOffice, porque desde todas las demás aplicaciones se imprimía sin problemas. Otros han notado que el problema va y viene. Un usuario encontró una solución: desinstalar OpenOffice y limpiar el sistema, luego reinstalar (cualquier tarea simple en Ubuntu). El usuario informó el martes que su problema de impresión había sido resuelto.



Dos semanas después, escribió (el martes) que su solución todavía no funcionaba. Aproximadamente cuatro meses después, la esposa del hacker de Ubuntu se quejó de que OpenOffice no imprimía los martes. Imagínese esta situación:



Esposa: Steve, la impresora está cerrada los martes.



Steve: Es un día libre en la imprenta, por supuesto que no imprime los martes.



Esposa: ¡Lo digo en serio! No puedo imprimir desde OpenOffice los martes.



Steve: (incrédulo) Está bien, enséñamelo.



Esposa: No puedo mostrártelo.



Steve: (poniendo los ojos en blanco) ¿Por qué?



Esposa: ¡Hoy es miércoles!



Steve: (asiente, habla despacio) Correcto.



El problema se remonta a un programa llamado file. Esta utilidad * NIX utiliza plantillas para detectar tipos de archivos. Por ejemplo, si el archivo comienza con%!y luego va PS-Adobe-, luego es PostScript. Parece que OpenOffice está escribiendo datos en dicho archivo. El martes se quita el uniforme %%CreationDate: (Tue MMM D hh:mm:...). Un error en la plantilla para archivos Erlang JAM significaba que Tueel archivo PostScript se reconocía como un archivo Erlang JAM y, por lo tanto, presumiblemente, no se estaba enviando a imprimir.



La plantilla para el archivo Erlang JAM se ve así:



4 string Tue Jan 22 14:32:44 MET 1991 Erlang JAM file - version 4.2


Y debería verse así:



4 string Tue\ Jan\ 22\ 14:32:44\ MET\ 1991 Erlang JAM file - version 4.2


Dada la multitud de tipos de archivos que este programa intenta reconocer (más de 1600), los errores de plantilla no son sorprendentes. Pero el orden de comparación también conduce a frecuentes falsos positivos. En este caso, el tipo Erlang JAM se asignó al tipo PostScript.



Paquetes de muerte



Empecé a llamarlos así porque eran exactamente paquetes de muerte.



Star2Star se ha asociado con un fabricante de hardware que ha creado las dos últimas versiones de nuestro sistema cliente local.



Hace aproximadamente un año lanzamos una actualización para este hardware. Todo comenzó bastante simple, siguiendo la ley habitual de Moore. Más grande, mejor, más rápido, más barato. El nuevo hardware era de 64 bits, tenía 8 veces más memoria, contenía más unidades y tenía cuatro puertos Intel Gigabit Ethernet (mi fabricante favorito de controladores Ethernet). Teníamos (y todavía tenemos) muchas ideas sobre cómo usar estos puertos. En general, la pieza de hierro fue asombrosa.



La novedad pasó rápidamente por las pruebas de rendimiento y funcionalidad. Tanto la velocidad es alta como la fiabilidad. Idealmente. Luego, implementamos lentamente el equipo en varios sitios de prueba. Por supuesto, empezaron a surgir problemas.



Una búsqueda rápida en Google sugiere que el controlador Ethernet Intel 82574L tenía al menos algunos problemas. En particular, problemas con EEPROM, errores en ASPM, trucos con MSI-X, etc. Llevamos varios meses resolviendo cada uno de ellos. Y pensamos que habíamos terminado.



Pero no. Solo empeoró.



Pensé que diseñé e implementé la imagen de software perfecta (y BIOS). Sin embargo, la realidad fue diferente. Los módulos siguieron fallando. A veces se recuperaron después de reiniciar, a veces no. Sin embargo, una vez restaurado el módulo, era necesario probarlo.



Guau. La situación se estaba volviendo extraña.



Las rarezas continuaron, y finalmente decidí arremangarme. Tuve la suerte de encontrar un revendedor muy paciente y servicial que se quedó conmigo en mi teléfono durante tres horas mientras recopilaba datos. En ese punto del cliente, por alguna razón, el controlador Ethernet podría caer mientras transmite tráfico de voz a través de la red.



Me detendré en esto con más detalle. Cuando digo que el controlador de Ethernet “podría haberse averiado”, significa que PODRÍA haber desaparecido. El sistema y la interfaz Ethernet se veían bien y, después de enviar una cantidad aleatoria de tráfico, la interfaz podría informar un error de hardware (pérdida de comunicación con la PHY) y perder la conexión. Los LED del interruptor y la interfaz literalmente se apagaron. El controlador estaba muerto.



Era posible devolverlo a la vida solo apagando y encendiendo la alimentación. Intentar reiniciar un módulo del kernel o una máquina resultó en un error de escaneo PCI. La interfaz permaneció inactiva hasta que la máquina se desconectó físicamente y se volvió a conectar. En la mayoría de los casos, para nuestros clientes, esto significaba retirar el equipo.



Mientras depuraba con este revendedor tan paciente, comencé a dejar de recibir paquetes cuando la interfaz fallaba. Al final, identifiqué un patrón: el último paquete de la interfaz era siempre 100 Trying provisional response, y siempre tenía una cierta longitud. Eso no es todo, eventualmente rastreé esta respuesta (de Asterisk) hasta la solicitud INVITE original específica para uno de los teléfonos de los fabricantes.



Llamé al revendedor, reuní a la gente y mostré la evidencia. Aunque era viernes por la noche, todos participaron en el trabajo y armaron un banco de pruebas con nuestros nuevos equipos y teléfonos de este fabricante.



Nos sentamos en una sala de conferencias y comenzamos a marcar tan rápido como nuestros dedos podían. ¡Resultó que podemos reproducir el problema! No en todas las llamadas ni en todos los dispositivos, pero de vez en cuando logramos encender el controlador Ethernet y de vez en cuando no lo hacíamos. Después de perder energía, lo intentamos de nuevo y lo logramos. En cualquier caso, como sabe cualquiera que haya intentado diagnosticar problemas técnicos, el primer paso es reproducir el problema. Finalmente lo hemos logrado.



Créame, tomó mucho tiempo. Sé cómo funciona la pila OSI. Sé cómo se segmenta el software. Sé que el contenido de los paquetes SIP no debería afectar al adaptador Ethernet. Todo es una tontería.



Finalmente, logramos aislar el problema de los paquetes en el intervalo entre su llegada a nuestro dispositivo y al puerto espejo en el switch. Resultó que el problema estaba en la solicitud INVITE, no en la respuesta 100 Trying. No 100 Tryinghubo respuesta en los datos capturados en el puerto reflejado .



Era necesario lidiar con esto INVITE. ¿El problema estaba relacionado con el manejo de este paquete por el demonio del espacio de usuario? ¿Quizás la transmisión fue el problema 100 Trying? Uno de mis colegas sugirió cerrar la aplicación SIP y ver si el problema persiste. Sin esta aplicación, los paquetes100 Tryingno fueron transmitidos.



Era necesario mejorar de alguna manera la transmisión de paquetes problemáticos. Aislamos el paquete transmitido desde el teléfono INVITEy lo reproducimos usando tcpreplay. Funcionó. Por primera vez en meses, pudimos eliminar puertos por comando con un solo paquete. Este fue un avance significativo, y era hora de volver a casa, es decir, ¡de repetir el banco de pruebas en el laboratorio de casa!



Antes de continuar con mi historia, quiero contarles acerca de una gran aplicación de código abierto que encontré. Ostinato te convierte en un maestro de paquetes. Sus posibilidades son literalmente infinitas. Sin esta aplicación, no habría podido progresar más.



Armado con esta herramienta de paquete versátil, comencé a experimentar. Me asombró lo que encontré.



Todo comenzó con una extraña peculiaridad SIP / SDP. Eche un vistazo a este SDP:



v=0
o=- 20047 20047 IN IP4 10.41.22.248
s=SDP data
c=IN IP4 10.41.22.248
t=0 0
m=audio 11786 RTP/AVP 18 0 18 9 9 101
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:0 PCMU/8000
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:9 G722/8000
a=rtpmap:9 G722/8000
a=fmtp:101 0-15
a=rtpmap:101 telephone-event/8000
a=ptime:20
a=sendrecv


Sí, eso es correcto. Se duplica la propuesta de transmisión de sonido. Esto es un problema, pero de nuevo, ¿qué tiene que ver el controlador Ethernet con esto? Bueno, aparte del hecho de que nada más aumenta el tamaño de la trama Ethernet ... Pero espere, hubo muchas tramas Ethernet exitosas en los paquetes transmitidos. Algunos de ellos eran más pequeños, otros más. No hubo problemas con ellos. Tuve que investigar más. Después de algunos trucos de kung fu con Ostinato y un montón de reconexiones eléctricas, pude identificar la relación problemática (con el cuadro del problema). Nota: estaremos mirando valores hexadecimales.



Un bloqueo de la interfaz se inició con un valor de byte específico en un desplazamiento específico. En nuestro caso, fue el valor hexadecimal 32c 0x47f. En ASCII, hexadecimal 32es2... Adivina de dónde vino 2.



a=ptime:20


Todos nuestros SDP eran idénticos (incluidos ptime). Todos los URI de origen y destino eran idénticos. Las únicas diferencias fueron el número de la persona que llama, las etiquetas y los ID de sesión únicos. Los paquetes problemáticos tenían tal combinación de ID de llamadas, etiquetas y ramas, lo que ptimeresultó en un valor 2con un desplazamiento 0x47f.



¡Auge! Con las ID, etiquetas y ramas correctas (o cualquier basura aleatoria), un "buen paquete" podría convertirse en un paquete "asesino" tan pronto como la línea ptimeterminara en una determinada dirección. Fue muy extraño.



Al generar paquetes, experimenté con diferentes valores hexadecimales. La situación resultó ser aún más complicada. Resultó que el comportamiento del controlador dependía por completo de este valor particular ubicado en la dirección especificada en el primer paquete recibido. La imagen era así:



 0x47f = 31 HEX (1 ASCII) -  
 0x47f = 32 HEX (2 ASCII) -  
 0x47f = 33 HEX (3 ASCII) -  
 0x47f = 34 HEX (4 ASCII) -  (inoculation) 


Cuando dije "no afecta", quise decir que no solo no mata la interfaz, sino que tampoco inocula (más o menos). Y cuando digo que "la interfaz falla", bueno, ¿recuerdas mi descripción? La interfaz está muriendo. Completamente.



Después de nuevas pruebas, descubrí que el problema persiste con todas las versiones de Linux que pude encontrar, con FreeBSD, ¡e incluso al encender la máquina sin un dispositivo de arranque! Se trataba del hardware, no del sistema operativo. Guau.



Además, con la ayuda de Ostinato, pude crear diferentes versiones del paquete asesino: HTTP POST, solicitud de eco ICMP y otras. Casi todo lo que quería. Con un servidor HTTP modificado que generaba datos en valores de bytes (basados ​​en encabezados, host, etc.), fue fácil crear la solicitud HTTP número 200 para contener el paquete de muerte y matar las máquinas cliente detrás del firewall.



Ya he explicado lo extraña que era toda la situación. Pero lo más extraño fue con la vacuna. Resultó que si el primer paquete recibido contiene algún valor (probado por mí), con la excepción 1, 2o 3, si la interfaz se vuelve invulnerable a cualquier paquete, la muerte (que contiene el valor 2o 3). Por otra parte, los códigos y atributos ptimehan sido múltiplos de 10: 10, 20, 30, 40. Dependiendo de la combinación de ID de llamada, Etiqueta, Rama, IP, URI y más (con este SDP con errores), estos atributos válidos se ptimealinearon en una secuencia perfecta. ¡Increíble!



De repente quedó claro por qué el problema se producía de forma esporádica. Es asombroso que pude entenderlo. Llevo 15 años trabajando con redes y nunca había visto nada igual. Y dudo que te vuelva a ver. Con suerte ...



Me puse en contacto con dos ingenieros de Intel y les envié una demostración para que pudieran reproducir el problema. Después de experimentar durante un par de semanas, descubrieron que el problema estaba en la EEPROM de los controladores 82574L. Me enviaron una nueva EEPROM y una herramienta de escritura. Desafortunadamente, no pudimos distribuirlo, y además, fue necesario descargar y recargar el módulo del kernel e1000e, por lo que la herramienta no era adecuada para nuestro entorno. Afortunadamente (con un poco de conocimiento del esquema EEPROM) pude escribir un script bash y luego mágicamenteethtoolguardó los valores "fijos" y los registró en los sistemas donde se manifestó el error. Ahora podríamos identificar los dispositivos con problemas. Nos hemos puesto en contacto con nuestro proveedor para aplicar el parche a todos los dispositivos antes de enviárnoslo. No se sabe cuántos de estos controladores Intel Ethernet ya se han vendido.



Un palet mas



En 2005, tuve un problema inexplicable en el trabajo. Un día después del cierre no planificado (debido al huracán), comencé a recibir llamadas de usuarios que se quejaban de los tiempos de espera al conectarse a la base de datos. Como teníamos una red muy simple para 32 nodos y con un ancho de banda prácticamente sin usar, me alarmó que el servidor con la base de datos hiciera ping normalmente durante 15-20 minutos, y luego las respuestas de “solicitud agotada” llegaron en unos dos minutos. Este servidor estaba ejecutando el monitoreo del rendimiento y otras herramientas y haciendo ping desde varias ubicaciones. Con la excepción del servidor, el resto de las máquinas podrían comunicarse con otros miembros de la red todo el tiempo. Busqué un interruptor o conexión fallidos, pero no pude encontrar una explicación para los fallos aleatorios e intermitentes.



Le pedí a un colega que observara los LED del interruptor en el almacén mientras rastreaba y volvía a conectar varios dispositivos. Tardaron 45-50 minutos, un colega me dijo en la radio "este está apagado, ese se levantó". Le pregunté si notaba algún patrón.



- Sí, lo noté. Pero pensarás que estoy loco. Cada vez que un montacargas saca un palé de la sala de envío, se produce un tiempo de espera después de dos segundos en el servidor.



- ¿¿¿QUÉ???



- Si. Y el servidor se restaura cuando el cargador comienza a enviar un nuevo pedido.



Corrí a mirar el montacargas y estaba seguro de que estaba marcando la finalización exitosa de la orden al encender un magnetrón gigante. Sin duda, las ondas electromagnéticas del condensador provocan una ruptura en el continuo espacio-tiempo e interrumpen temporalmente el funcionamiento de la tarjeta de red del servidor ubicada en otra habitación a 50 metros de distancia. No. La carretilla elevadora simplemente apiló cajas más grandes en el palé con cajas más pequeñas en la parte superior, mientras escaneaba cada caja con un escáner de código de barras inalámbrico. ¡Ajá! Probablemente sea el escáner el que está accediendo al servidor de la base de datos, lo que provoca que otras consultas fallen. No Lo comprobé y descubrí que el escáner no tenía nada que ver con eso. El enrutador inalámbrico y su UPS en la sala de envío se configuraron correctamente y funcionaron normalmente. El motivo fue otra cosa, porque antes del cierre por el huracán todo funcionaba bien.



Tan pronto como comenzó el siguiente tiempo de espera, corrí a la sala de envío y observé cómo el cargador llenaba la siguiente paleta. Tan pronto como colocó cuatro cajas grandes de champú en una bandeja vacía, ¡el servidor volvió a caer! No creía en lo absurdo de lo que estaba pasando, y durante otros cinco minutos saqué y puse cajas de champú, con el mismo resultado. Estaba a punto de caer de rodillas y rezar por la misericordia del Dios de la intranet cuando noté que el enrutador en la sala de envío estaba colgando unos 30 cm por debajo del nivel de las cajas en el palet. ¡Hay una pista!



Cuando se colocaron cajas grandes en un palé, el enrutador inalámbrico perdió la línea de visión con el almacén exterior. Después de diez minutos, resolví el problema. Esto es lo que sucedió. Durante el huracán, hubo un corte de energía que dejó caer el único dispositivo que no estaba conectado al UPS: un enrutador inalámbrico de prueba en mi oficina. La configuración predeterminada de alguna manera lo convirtió en un repetidor para el único otro enrutador inalámbrico que colgaba en la sala de envío. Ambos dispositivos solo podían comunicarse entre sí cuando no había una paleta entre ellos, pero incluso entonces la señal no era demasiado fuerte. Cuando los enrutadores hablaron, crearon un bucle en mi pequeña red y luego se perdieron todos los demás paquetes al servidor de la base de datos. El servidor tenía su propio conmutador desde el enrutador principal, por lo tanto, como nodo de red, estaba mucho más lejos.La mayoría de las otras computadoras estaban en el mismo conmutador de 16 puertos, por lo que podía hacer ping entre ellas sin ningún problema.



En un segundo, resolví un problema que me atormentó durante cuatro horas: apagué la alimentación del enrutador de prueba. No hubo más tiempos de espera en el servidor.



Como la película Tron, solo en una computadora Apple IIgs



Una de mis películas favoritas de niño fue Tron, que se filmó a principios de la década de 1980. Hablaba de un programador que estaba "digitalizado" y estaba absorto en el mundo de la informática habitado por programas personalizados. El protagonista se unió a un grupo de resistencia en un intento de derrocar al opresor Master Control Program (MCP), un programa rebelde que evolucionó, ganó un deseo de poder e intentó apoderarse del sistema informático del Pentágono.



En una de las escenas más impresionantes de los programas, los personajes corren en bicicletas ligeras: autos de dos ruedas que parecen motocicletas que dejan paredes detrás de ellos. Uno de los protagonistas obligó a los pepelats enemigos a estrellarse contra la pared de la arena, haciendo un agujero pasante. Los héroes lidiaron con sus oponentes y huyeron por el agujero hacia la libertad, el primer paso hacia el derrocamiento del MCP.



Cuando vi la película, no tenía idea de que años después, sin darme cuenta, recrearía el mundo de Tron, los programas rebeldes y todo lo demás en una computadora Apple IIgs.



Así sucedió. Cuando comencé a aprender a programar, decidí crear un juego de ciclo ligero de Tron. Junto con mi amigo Marco, escribí un programa sobre Apple IIgs en ORCA / Pascal y ensamblador 65816. Durante el juego, la pantalla se pintó de negro con un borde blanco. Cada línea representa a uno de los jugadores. Mostramos las puntuaciones de los juegos en una fila en la parte inferior de la pantalla. Gráficamente, no era el programa más avanzado, pero era sencillo y divertido. Ella se veía así:





El juego admitía hasta cuatro jugadores si se sentaban frente a un teclado. Fue un inconveniente, pero funcionó. Rara vez logramos que la cantidad adecuada de personas usaran los cuatro ciclos de luz, por lo que Marco agregó jugadores controlados por computadora que podían competir razonablemente.



Carrera de armamentos



El juego ya era muy divertido, pero queríamos experimentar. Agregamos cohetes para que los jugadores tengan la oportunidad de escapar de un accidente inminente. Como Marco describió más tarde:



Los humanos y la IA tenían cada uno tres cohetes que podían usarse durante el juego. Cuando el cohete chocó contra la pared, se produjo una "explosión", cuyo fondo se pintó de negro, eliminando tramos del rastro dejado por los ciclos de luz anteriores.


Pronto, los jugadores y las computadoras podrían salir disparados de situaciones difíciles con cohetes. Aunque los puristas de Tron se reirán de eso, los programas de la película no tenían el lujo de los cohetes.



El escape



Como ocurre con todos los eventos inusuales y extraños, también fue inesperado.



Una vez, cuando Marco y yo estábamos jugando contra dos jugadores de computadora, atrapamos uno de los bucles de IA entre su propia pared y el borde inferior de la pantalla. Anticipándose a un accidente inminente, disparó un cohete, como siempre hacía antes. Pero esta vez, en lugar de una pared, disparó al borde de la pantalla, que parecía el rastro de uno de los ciclos de luz. El misil golpeó la frontera, dejó un agujero del tamaño de un ciclo de luz y la computadora salió inmediatamente del campo de juego a través de él. Miramos confundidos el ciclo de luz mientras pasaba a través de la línea marcada. Evitó fácilmente chocar con los símbolos y luego abandonó la pantalla por completo.



E inmediatamente después de eso, el sistema se bloqueó.





Nuestras mentes se tambalearon mientras tratábamos de comprender lo que había sucedido. La computadora encontró una manera de salir del juego. Cuando el ciclo de luz salió de la pantalla, se escapó a la memoria de la computadora, como en la película. Nos quedamos boquiabiertos cuando nos dimos cuenta de lo que había sucedido.



¿Qué hicimos cuando descubrimos un defecto en nuestro programa que regularmente podría bloquear todo el sistema? Lo hicimos todo de nuevo. Primero intentamos salirnos de los límites nosotros mismos. Luego obligaron a la computadora a huir nuevamente. Cada vez que fuimos recompensados ​​con encantadores fallos del sistema. A veces, la luz de la unidad parpadeaba mientras la unidad rezongaba interminablemente. Otras veces, la pantalla se llenaba de caracteres sin sentido o el hablante emitía un chillido o un zumbido bajo. Y a veces todo sucedía a la vez, y la computadora estaba en un estado de completo desorden.



¿Por qué pasó esto? Para entender esto, veamos la arquitectura de la computadora Apple IIgs.



Memoria (des) protegida



El sistema operativo Apple IIgs no tenía memoria protegida, que apareció en sistemas operativos posteriores cuando se asignaron áreas de memoria a un programa y se protegieron del acceso externo. Por lo tanto, un programa para Apple IIgs podría leer y escribir cualquier cosa (excepto ROM). IIgs usaba E / S ligadas a la memoria para acceder a dispositivos como la disquetera, por lo que era posible activar la disquetera leyendo desde un área específica de la memoria. Esta arquitectura permitió que los programas gráficos leyeran y escribieran directamente en la memoria de la pantalla.



El juego utilizó uno de los modos gráficos de Apple IIgs: Super Hi-Res: una resolución asombrosa de 320x200 píxeles con una paleta de 16 colores. Para seleccionar una paleta, el programador especificó 16 entradas (numeradas de 0 a 15 o de $ 0 a F en formato hexadecimal) para valores de color de 12 bits. Para dibujar en la pantalla, puede leer y escribir colores directamente en la memoria de video.



Algoritmo de detección de colisiones



Aprovechamos esta función e implementamos un detector de accidentes leyendo directamente desde la memoria de video. El juego calculó para cada ciclo de luz su siguiente posición basándose en la dirección actual y leyó este píxel de la memoria de video. Si la posición estaba vacía, es decir, representada por un píxel negro (entrada en la paleta de $ 0), entonces el juego continuaba. Pero si se tomó la posición, el jugador chocó contra el ciclo de luz o el marco blanco de la pantalla (entrada en la paleta 15 o $ F). Ejemplo:





Aquí se muestra la esquina superior izquierda de la pantalla. El color $ F denota un borde blanco y el color $ 1 denota el ciclo de luz verde del jugador. Se mueve hacia la izquierda como lo muestra la flecha, es decir, el siguiente píxel está vacío, su color es $ 0. Si el jugador continúa moviéndose en esta dirección durante más de un turno, chocará con una pared (color $ F) y se romperá.



Ir más allá



El algoritmo para determinar el siguiente píxel usando matemáticas de ensamblador calculó rápidamente la dirección de memoria de un píxel arriba, abajo, a la izquierda oa la derecha del píxel actual. Dado que cualquier píxel en la pantalla era una dirección en la memoria, el algoritmo simplemente calculó una nueva dirección para leer. Y cuando el ciclo de luz abandonó la pantalla, el algoritmo determinó un lugar en la memoria del sistema para verificar si había una colisión con una pared. Esto significaba que el ciclo de luz ahora atravesaba la memoria del sistema, activando bits sin sentido y "chocando" contra la memoria.



Escribir en ubicaciones aleatorias en la memoria del sistema no es una decisión arquitectónica inteligente. Como era de esperar, el juego se bloqueó debido a esto. Un jugador humano no viajará a ciegas y, por lo general, se estrellará de inmediato, lo que limita el alcance de los problemas del sistema. Y la IA no tiene tal debilidad. La computadora escanea instantáneamente las posiciones a su alrededor para determinar si golpea una pared y cambia de dirección. Es decir, desde el punto de vista de la computadora, la memoria del sistema no era diferente de la memoria de la pantalla. Como lo describió Marco:



, , . , , 0. «» , . «», - - , , — . , - , .


Como resultado, no solo recreamos la carrera del ciclo de luz de la película, sino también el escape en sí. Como en la película, la fuga tuvo grandes consecuencias.



Esto es difícil de repetir hoy, ya que los sistemas operativos han adquirido memoria protegida. Pero todavía me pregunto si hay programas como Tron que están tratando de escapar de sus "espacios protegidos" en un intento de evitar que el código rebelde de la IA se apodere del Pentágono.



Supongo que para averiguarlo, tenemos que esperar a que se invente la digitalización de la conciencia.



Siéntate para iniciar sesión



Todo programador sabe que la depuración es difícil. Aunque, para los depuradores excelentes, el trabajo parece engañosamente simple. Los programadores angustiados describen un error que pasan horas detectando, el maestro hace algunas preguntas y, después de unos minutos, los programadores ven un código defectuoso frente a ellos. Un experto en depuración no olvida que siempre hay una explicación lógica, por misterioso que se comporte el sistema a primera vista.



Esta actitud está ilustrada por una historia que tuvo lugar en el Centro de Investigación de IBM Yorktown Heights. El programador instaló recientemente una nueva estación de trabajo. Todo estaba bien cuando estaba sentado frente a la computadora, pero no podía iniciar sesión mientras estaba de pie. Este comportamiento siempre se reproducía: el programador siempre iniciaba sesión mientras estaba sentado, pero no podía ni una vez mientras estaba de pie.



Muchos de nosotros simplemente nos sentamos allí y nos preguntamos. ¿Cómo podría saber la computadora si estaban parados frente a ella o sentados? Sin embargo, los buenos depuradores saben que debe haber una razón. Lo primero que me viene a la mente es la electricidad. ¿Alambre roto debajo de la alfombra o electricidad estática? Pero los problemas eléctricos rara vez se reproducen el 100% del tiempo. Uno de los colegas finalmente hizo la pregunta correcta: ¿cómo se conectaba el programador mientras estaba sentado y de pie? Inténtalo tú mismo.



La razón fue el teclado: los dos botones estaban invertidos. Cuando el programador estaba sentado, escribía a ciegas y el problema pasaba desapercibido. Y cuando se paró, lo confundió, buscó botones y los presionó. Armado con esta pista y un destornillador, el experto en depuración cambió los botones y todo funcionó.



El sistema bancario desplegado en Chicago funcionó bien durante muchos meses. Pero se cerró inesperadamente cuando se utilizó por primera vez para procesar datos internacionales. Los programadores hurgaron en el código durante días, pero no pudieron encontrar un solo comando que condujera a la finalización del programa. Cuando observaron más de cerca su comportamiento, descubrieron que el programa terminaría cuando se ingresaran los datos de Ecuador. El análisis mostró que cuando el usuario escribió el nombre de la capital (Quito), ¡el programa lo interpretó como un comando de salida!



Un día, Bob Martin se encontró con un sistema que "funcionaba una vez dos veces". Manejó la primera transacción correctamente y hubo problemas menores en todas las transacciones posteriores. Cuando se reinició el sistema, nuevamente procesó correctamente la primera transacción y falló en todas las siguientes. Cuando Bob describió este comportamiento como "ejecutarse una vez dos veces", los desarrolladores se dieron cuenta inmediatamente de que necesitaban buscar una variable que se inicializara correctamente cuando se cargó el programa, pero que no se restableció después de la primera transacción. En todos los casos, las preguntas correctas permitieron a los programadores inteligentes identificar rápidamente errores desagradables: “¿Qué hizo de manera diferente cuando estaba de pie y sentado? Muéstrame cómo inicias sesión en ambos casos "," ¿Qué ingresaste exactamente antes del final del programa? " “¿El programa funcionó correctamente antes de que comenzaran los accidentes? ¿Cuantas veces?"



Rick Lemons dijo que la mejor lección que aprendió sobre la depuración fue cuando vio actuar al mago. Había hecho una docena de trucos imposibles y Lemons sintió que creía en ellos. Luego se recordó a sí mismo que lo imposible no es posible, y probó todos los trucos para demostrar esta obvia inconsistencia. Lemons comenzó con lo que era una verdad inquebrantable: las leyes de la física, y a partir de ellas comenzó a buscar explicaciones simples para cada truco. Esta actitud convierte a Lemons en uno de los mejores depuradores que he conocido.



El mejor libro de depuración en mi opinión es The Medical Detectives, escrito por Berton Roueche y publicado por Penguin en 1991. Los héroes del libro depuran sistemas complejos, desde una persona moderadamente enferma hasta ciudades muy enfermas. Los métodos de resolución de problemas utilizados allí se pueden utilizar directamente para depurar sistemas informáticos. Estas historias reales son tan fascinantes como cualquier ficción.



El caso de correo electrónico de 500 millas



Aquí hay una situación que sonaba inconcebible ... Casi me negué a hablar de ella porque es una gran bicicleta para conferencias. Modifiqué ligeramente la historia para proteger al culpable, para descartar detalles irrelevantes y aburridos y, en general, para hacer la historia más atractiva.



Hace varios años, estaba sirviendo un sistema de correo electrónico en el campus. El jefe del departamento de estadística me llamó.



- Tenemos un problema con el envío de cartas.



- ¿Cuál es el problema?



“No podemos enviar cartas a más de 500 millas.



Me atraganté con mi café.



- No se entiende.



“No podemos enviar cartas del departamento a más de 500 millas. De hecho, un poco más lejos. Aproximadamente 520 millas. Pero este es el límite.



"Hmm ... En realidad, el correo electrónico no funciona de esa manera", respondí, tratando de controlar el pánico en mi voz. No se puede mostrar pánico en una conversación con el jefe de un departamento, ni siquiera uno como el departamento de estadística. - ¿Por qué decidió que no puede enviar cartas a más de 500 millas?



"No lo he decidido ", respondió con voz fuerte. - Verás, cuando nos dimos cuenta de lo que estaba pasando hace unos días ...



- ¿Esperaste unos DÍAS? Lo interrumpí con voz temblorosa. - ¿Y no pudiste enviar cartas todo este tiempo?



- Podríamos enviar. Simplemente no más…



”“ Quinientas millas, sí, ”terminé por él. - Claro. ¿Pero por qué no llamaste antes?



“Bueno, hasta este punto no teníamos suficientes datos para estar seguros de lo que estaba sucediendo.



Exactamente, este es el jefe de estadísticas .



- De todos modos, le pedí a uno de los geoestadísticos que trabajara con esto ...



- Geoestadísticos ...



- Sí, e hizo un mapa que muestra el radio dentro del cual podemos enviar cartas, un poco más de 500 millas. Hay varios lugares en esta zona donde nuestras cartas no llegan en absoluto o periódicamente, pero fuera del radio no podemos enviar nada en absoluto.



"Ya veo", dije, y dejé caer la cabeza entre mis manos. - ¿Cuando empezó? Lo dijiste hace unos días, pero no hemos cambiado nada en tus sistemas.



- Vino un consultor, parcheó y reinició nuestro servidor. Pero lo llamé y me dijo que no tocó el sistema de correo.



"Está bien, déjame echar un vistazo y devolverte la llamada", respondí, sin apenas creer que estaba participando en tal cosa. Hoy no era el primero de abril. Traté de recordar si alguien me debía una broma.



Ingresé al servidor de su departamento y envié algunos correos electrónicos de verificación. Esto tuvo lugar en el Triángulo de Investigación de Carolina del Norte y la carta llegó a mi buzón sin ningún problema. También lo hicieron las cartas enviadas a Richmond, Atlanta y Washington. También se envió una carta a Princeton (400 millas).



Pero luego envié una carta a Memphis (600 millas). No llegó. En Boston, no llegó. En Detroit, no llegó. Saqué mi libreta de direcciones y comencé a enviar cartas a través de ella. Llegó a Nueva York (420 millas), pero no llegó a Providence (580 millas).



Empecé a dudar de mi cordura. Le escribió a un amigo en Carolina del Norte cuyo proveedor estaba en Seattle. Afortunadamente, la carta no llegó. Si el problema fuera la ubicación de los destinatarios, no sus servidores de correo, probablemente me habría echado a llorar.



Después de descubrir que el problema existía (increíblemente) y era reproducible, comencé a analizar el archivo sendmail.cf. Se veía bien. Como siempre. Lo comparé con sendmail.cf en mi directorio personal. No hubo diferencia, fue el archivo que escribí. Y estaba bastante seguro de que no incluí la opción FAIL_MAIL_OVER_500_MILES. Confundido, hice telnet al puerto SMTP. El servidor respondió felizmente con un banner de Sendmail de SunOS.



Espera ... ¿el banner de Sendmail de SunOS? En ese momento, Sun todavía estaba enviando Sendmail 5 con su sistema operativo, aunque Sendmail 8 ya estaba completamente implementado. Como era un buen administrador de sistemas, presenté Sendmail 8 como estándar. Además, como era un buen administrador de sistemas, escribí sendmail.cf, que utilizaba las opciones largas y geniales de autodocumentación y los nombres de variables disponibles en Sendmail 8, en lugar de los códigos de puntuación crípticos utilizados en Sendmail 5.



Todo encajó. y me atraganté con mi café ya enfriado de nuevo. Parece que cuando el consultor "parcheó el servidor", actualizó la versión de SunOS desde la cual lanzó una versión anterior de Sendmail. Afortunadamente, el archivo sendmail.cf sobrevivió, pero ahora no coincidía.



Resultó que Sendmail 5, al menos la versión enviada por Sun que tenía varias mejoras, podía funcionar con sendmail.cf para Sendmail 8, porque la mayoría de las reglas eran las mismas. Pero las nuevas opciones de configuración larga ahora no se reconocen ni se descartan. Y como no había valores predeterminados en el binario de Sendmail para la mayoría de ellos, el programa no encontró ningún valor adecuado en sendmail.cf y los restableció a cero.



Uno de estos valores puestos a cero fue el tiempo de espera de la conexión a un servidor SMTP remoto. Después de un poco de experimentación, resultó que en esta máquina en particular, bajo carga normal, un tiempo de espera cero conduce a una desconexión en poco más de tres milisegundos.



En ese momento, la red del campus estaba completamente basada en conmutadores. El paquete saliente no se retrasó hasta que llegó al enrutador del otro lado a través de POP. Es decir, la duración de una conexión a un host remoto con poca carga en una red vecina dependía principalmente de la distancia recorrida a la velocidad de la luz y no de retrasos aleatorios de los enrutadores.



Sintiéndome un poco mareado, entré en la línea de comando:



$ units
1311 units, 63 prefixes

You have: 3 millilightseconds
You want: miles
        * 558.84719
        / 0.0017893979


"500 millas o más".






Continuará.



All Articles