Folclore de programadores e ingenieros (parte 1)





Esta es una colección de historias de Internet sobre cómo los errores a veces tienen manifestaciones increíbles. Quizás también tengas una historia que contar.



Alergia al coche al helado de vainilla



Una historia para ingenieros que entienden que lo obvio no siempre es la solución y que, por muy inverosímiles que sean los hechos, son hechos. La División Pontiac de General Motors Corporation recibió una queja:



, , , . : . , , , , . Pontiac, . , , , . , . , , : « Pontiac, - , , , ?».


Como puede imaginar, el presidente de la división se mostró escéptico sobre la carta. Sin embargo, por si acaso, envié a un ingeniero a verificar. Se sorprendió al encontrarse con un hombre rico y bien educado que vivía en una hermosa zona. Acordaron reunirse justo después de la cena para ir juntos a la heladería. Era vainilla esa noche, y cuando regresaron al auto, no arrancaba.



El ingeniero vino tres tardes más. La primera vez que el helado fue de chocolate. El coche arrancó. La segunda vez hubo helado de fresa. El coche arrancó. A la tercera noche, pidió vainilla. El auto no arrancó.



Habiendo razonado sabiamente, el ingeniero se negó a creer en la alergia del automóvil al helado de vainilla. Por eso, acordé con el dueño del auto que continuará sus visitas hasta que encuentre una solución al problema. Y en el camino, comenzó a tomar notas: anotó toda la información, la hora del día, el tipo de gasolina, la hora de llegada y regreso de la tienda, etc.



Pronto, el ingeniero se dio cuenta de que el propietario del automóvil pasaba menos tiempo comprando helado de vainilla. El motivo fue la distribución del producto en la tienda. El helado de vainilla era el más popular y se guardaba en un congelador separado en la parte delantera de la tienda para que fuera más fácil de encontrar. Y todas las demás variedades estaban en la parte trasera de la tienda, y tomó mucho más tiempo encontrar la variedad adecuada y pagar.



Ahora la pregunta era para el ingeniero: ¿por qué no arranca el automóvil, si pasa menos tiempo desde el momento en que se apaga el motor? Dado que el problema era el tiempo, no el helado de vainilla, el ingeniero rápidamente encontró la respuesta: era una cerradura de gas. Surgió todas las noches, pero cuando el dueño del auto pasó más tiempo buscando helado, el motor tuvo tiempo de enfriarse lo suficiente y arrancó silenciosamente. Y cuando el hombre compró helado de vainilla, el motor todavía estaba demasiado caliente y el tapón del gas no tuvo tiempo de disolverse.



Moraleja: Incluso los problemas completamente locos a veces pueden ser reales.



Crash Bandicoot



Es doloroso experimentar esto. Como programador, te acostumbras a culpar a tu código primero, segundo, tercero ... y en algún lugar del décimo milésimo lugar culpas al compilador. E incluso más abajo en la lista, ya culpas al equipo.



Aquí está mi historia sobre un error de hardware.



Para el juego Crash Bandicoot, escribí un código para cargar y guardar en una tarjeta de memoria. Para un desarrollador de juegos tan moralista, era como caminar en un parque: pensé que el trabajo llevaría varios días. Sin embargo, como resultado, depuré el código durante seis semanas. Resolví otros problemas en el camino, pero cada pocos días volvía a este código durante varias horas. Fue una agonía.



El síntoma se veía así: cuando guardas la partida actual del juego y accedes a la tarjeta de memoria, casi siempre todo sale bien ... Pero a veces la operación de lectura o escritura se completa con el tiempo de espera sin ninguna razón obvia. Las grabaciones cortas a menudo dañan la tarjeta de memoria. Cuando un jugador intenta guardar, no solo no puede guardar, sino que también destruye el mapa. Tortita.



Después de un tiempo, nuestra productora de Sony, Connie Bus, comenzó a entrar en pánico. No pudimos enviar el juego con este error, y después de seis semanas no entendí cuál era la causa de este problema. A través de Connie, contactamos a otros desarrolladores de PS1: ¿alguien ha encontrado un problema similar? No. Nadie tuvo problemas con la tarjeta de memoria.



Cuando no tiene ninguna idea para depurar, entonces casi el único enfoque es "divide y vencerás": eliminas más y más código del programa erróneo hasta que hay un fragmento relativamente pequeño, lo que aún causa un problema. Es decir, corta el programa pieza por pieza hasta que quede la parte que contiene el error.



Pero el caso es que es muy difícil cortar piezas de un videojuego. ¿Cómo ejecutarlo si eliminó el código de emulación de gravedad? ¿O dibujando personajes?



Por lo tanto, debe reemplazar módulos completos con stubs que pretenden estar haciendo algo útil, pero de hecho hacen algo muy simple que no puede contener errores. Tenemos que escribir esas muletas para que el juego funcione. Es un proceso lento y doloroso.



En resumen, lo hice. Eliminé más y más piezas de código hasta que hubo un código inicial que configura el sistema para iniciar el juego, inicializa el equipo para renderizar, etc. Por supuesto, en esta etapa, no pude hacer el menú de guardar y cargar, porque tendría que hacer un stub para todo el código gráfico. Pero podría pretender ser un usuario que usa la pantalla (invisible) para guardar y cargar y pide guardar y luego escribir en la tarjeta de memoria.



Como resultado, me quedé con un pequeño fragmento de código que todavía tenía el problema mencionado anteriormente, ¡pero hasta ahora estaba sucediendo al azar! La mayoría de las veces todo funcionaba bien, pero ocasionalmente se producían caídas. Eliminé casi todo el código del juego, pero el error seguía vivo. Esto fue desconcertante: el código restante realmente no hizo nada.



En algún momento, probablemente a las tres de la mañana, se me ocurrió una idea. Las operaciones de lectura y escritura (E / S) asumen una sincronización exacta. Cuando se trabaja con un disco duro, una tarjeta de memoria o un módulo Bluetooth, el código de bajo nivel responsable de la lectura y escritura lo hace de acuerdo con los pulsos del reloj.



Con la ayuda de un reloj, un dispositivo que no está conectado directamente al procesador se sincroniza con el código ejecutable en el procesador. El reloj determina la velocidad en baudios, la velocidad en baudios. Si hay una confusión con los tiempos, entonces el hardware o el software, o ambos, también están confundidos. Y esto es muy malo, porque los datos pueden corromperse.



¿Qué pasa si algo en nuestro código confunde los tiempos? Verifiqué todo lo relacionado con esto en el código del programa de prueba y noté que configuramos el temporizador programable en la PS1 a una frecuencia de 1 kHz (1000 ciclos por segundo). Esto es bastante, por defecto se ejecuta a 100 Hz cuando se inicia el decodificador. Y la mayoría de los juegos usan esta frecuencia.



Andy, el desarrollador del juego, configuró el temporizador en 1 kHz para que los movimientos se calcularan con mayor precisión. Andy es propenso a lo excesivo, y si emulamos la gravedad, ¡lo hacemos con la mayor precisión posible!



Pero, ¿qué pasa si acelerar el temporizador de alguna manera afecta la sincronización general del programa y, por lo tanto, el reloj que ajusta la velocidad en baudios de la tarjeta de memoria?



He comentado el código del temporizador. El error nunca volvió a ocurrir. Pero esto no significa que lo hayamos arreglado, porque el accidente ocurrió al azar. ¿Qué pasa si tengo suerte?



Unos días después, volví a experimentar con el programa de prueba. El error no se repitió. Volví al código base completo del juego y cambié el código de guardar y cargar para que el temporizador programable se restableciera a su valor original (100Hz) antes de acceder a la tarjeta de memoria, y luego volví a 1kHz. No hubo más choques.



Pero, ¿por qué sucedió esto?



Volví al programa de prueba nuevamente. Intenté encontrar cierta regularidad en la aparición de un error con un temporizador de 1 kHz. Finalmente, noté que el error ocurre cuando alguien juega con el controlador de PS1. Dado que rara vez haría esto yo mismo, ¿por qué necesitaría un controlador al probar guardar y cargar código? - Entonces no noté esta dependencia. Pero un día, uno de nuestros artistas estaba esperando a que terminara de probar, probablemente estaba maldiciendo en ese momento, y nerviosamente retorció el controlador en sus manos. Se ha producido un error. "Esperar lo ?! Bueno, ¡hazlo de nuevo! "



Cuando me di cuenta de que estos dos eventos están interconectados, pude reproducir fácilmente el error: comencé a escribir en la tarjeta de memoria, moví el controlador, dañé la tarjeta de memoria. A mí me pareció un error de hardware.



Fui a ver a Connie y le conté mi descubrimiento. Transmitió la información a uno de los ingenieros que diseñó la PS1. "Imposible", respondió, "no puede ser un problema de hardware". Le pedí a Connie que hablara con nosotros.



El ingeniero me llamó y discutimos con él en su inglés roto y mi japonés (extremadamente) roto. Finalmente dije: "Permítanme enviar mi programa de prueba de 30 líneas donde el movimiento del controlador causa un error". El acepto. Dijo que era una pérdida de tiempo y que estaba terriblemente ocupado trabajando en un nuevo proyecto, pero se daría por vencido porque somos un desarrollador muy importante para Sony. Limpié mi programa de prueba y se lo envié.



La noche siguiente (estábamos en Los Ángeles y él en Tokio) me llamó y se disculpó avergonzado. Fue un problema de hardware.



No sé exactamente cuál fue el error, pero por lo que escuché en la sede de Sony, configurar el temporizador a un valor lo suficientemente alto interferiría con los componentes de la placa base cerca del cristal del temporizador. Uno de ellos fue el controlador de velocidad en baudios de la tarjeta de memoria, que también establecía la velocidad en baudios para los controladores. No soy ingeniero, por lo que podría haber confundido algo.



Pero la conclusión es que hubo interferencia entre los componentes de la placa base. Y al transmitir datos simultáneamente a través del puerto del controlador y el puerto de la tarjeta de memoria con un temporizador que funciona a una frecuencia de 1 kHz, los bits desaparecieron, los datos se perdieron y la tarjeta se dañó.



Vacas malas



En la década de 1980, mi mentor Sergei escribió un software para el CM-1800, un clon soviético del PDP-11. Este microordenador se acaba de instalar en una estación de ferrocarril cerca de Sverdlovsk, un importante centro de transporte de la URSS. El nuevo sistema fue diseñado para el enrutamiento de vagones y flujos de mercancías. Pero resultó ser un error molesto que provocó bloqueos y bloqueos aleatorios. Las caídas siempre ocurrían cuando alguien volvía a casa por la noche. Pero a pesar de una cuidadosa investigación al día siguiente, la computadora funcionó correctamente con todas las pruebas manuales y automatizadas. Esto suele indicar una condición de carrera o algún otro error de concurrencia que se manifiesta en determinadas condiciones. Cansado de las llamadas nocturnas, Sergei decidió llegar al fondo y, en primer lugar, comprender qué condiciones en el patio de clasificación llevaron a una avería de la computadora.



Primero, recopiló estadísticas sobre todas las caídas inexplicables y construyó un gráfico basado en fechas y horas. El patrón era obvio. Después de observar durante unos días más, Sergey se dio cuenta de que podía predecir fácilmente el tiempo de futuras fallas del sistema.



Pronto se enteró de que las interrupciones solo ocurrieron cuando la estación estaba clasificando vagones de ganado del norte de Ucrania y el oeste de Rusia a un matadero cercano. Esto en sí mismo era extraño, porque el matadero era abastecido por granjas que estaban mucho más cerca en Kazajstán.



La planta de energía nuclear de Chernobyl explotó en 1986 y la lluvia radiactiva hizo que el área circundante fuera inhabitable. Grandes áreas en el norte de Ucrania, Bielorrusia y Rusia occidental han sido contaminadas. Sospechando un alto nivel de radiación en los autos que llegaban, Sergei desarrolló un método para probar esta teoría. Se prohibió a la población tener dosímetros, por lo que Sergei dejó a varios militares en la estación de tren. Después de varios tragos de vodka, logró convencer al soldado de que midiera el nivel de radiación en uno de los autos sospechosos. Resultó que el nivel es varias veces más alto que los valores habituales.



El ganado no solo emitía una fuerte radiación, su nivel era tan alto que provocó la pérdida accidental de trozos en la memoria del CM-1800, que se encontraba en el edificio contiguo a la estación.



Había escasez de alimentos en la URSS y las autoridades decidieron mezclar la carne de "Chernobyl" con carne de otras regiones del país. Esto hizo posible reducir el nivel general de radiactividad sin perder valiosos recursos. Al enterarse de esto, Sergei llenó inmediatamente los documentos de emigración. Y las caídas de la computadora se detuvieron por sí solas cuando el nivel de radiación disminuyó con el tiempo.



A través de las tuberías



Movietech Solutions una vez creó software para salas de cine para venta de entradas, venta de entradas y gestión general. La versión DOS de la aplicación insignia ha sido bastante popular entre las cadenas de cines pequeñas y medianas de América del Norte. Por lo tanto, no es sorprendente que cuando se anunció la versión de Windows 95, integrada con las últimas pantallas táctiles y quioscos de autoservicio, y equipada con todo tipo de herramientas de informes, también se hizo popular rápidamente. La mayor parte del tiempo, la actualización se realizó sin problemas. El personal de TI en el terreno instaló nuevo hardware, migró datos y el negocio continuó. Excepto cuando no continuó. Cuando esto sucedió, la empresa envió a James the Cleaner.



Aunque este apodo alude al tipo nefasto, el limpiador es solo una combinación de instructor, instalador y experto en todos los oficios. James podía pasar unos días en el lugar del cliente juntando todos los componentes, y luego, durante un par de días, le enseñó al personal cómo usar el nuevo sistema, resolviendo cualquier problema de hardware que pudiera surgir y ayudando al software en su período de formación.



Por lo tanto, no es de extrañar que en este momento tan agitado, James llegó a la oficina por la mañana y no tuvo tiempo de llegar a su escritorio, cuando fue recibido por el jefe, lleno de cafeína por encima de lo normal.



“Me temo que necesitas viajar a Annapolis en Nueva Escocia lo antes posible. Todo su sistema se averió y, después de una noche de trabajo junto con sus ingenieros, no podemos averiguar qué pasó. Parece que el servidor tiene una falla en la red. Pero solo después de que el sistema haya funcionado durante varios minutos.



- ¿No volvieron al antiguo sistema? - respondió James con bastante seriedad, aunque en su mente abrió los ojos con sorpresa.



- Exactamente: su especialista en TI "cambió de prioridades" y decidió irse con su antiguo servidor. James, han instalado el sistema en seis sitios y acaban de pagar por soporte premium, y su negocio ahora está en la década de 1950.



James se enderezó levemente.



- Eso es otro asunto. Bien, comencemos.



Cuando llegó a Annapolis, lo primero que hizo fue encontrar la primera sala de cine del cliente que tenía un problema. En el mapa tomado en el aeropuerto, todo parecía decente, pero los alrededores de la dirección deseada parecían sospechosos. No es un gueto, pero recuerda al cine negro. Cuando James estacionó en la acera en el centro, una prostituta se le acercó. Dado el tamaño de Annapolis, lo más probable es que fuera el único en toda la ciudad. Su aparición inmediatamente recordó al famoso personaje que ofrecía sexo por dinero en la pantalla grande. No, no sobre Julia Roberts, sino sobre Jon Voight [un indicio de la película "Midnight Cowboy" - aprox. por. ].



Después de enviar a la prostituta a casa, James fue al cine. El entorno ha mejorado, pero aún así se crea la impresión de cutre. No es que James estuviera demasiado preocupado. Ya había estado en lugares miserables. Y esto fue Canadá, donde incluso los ladrones son lo suficientemente amables como para agradecerles después de que se llevaron su billetera.



La entrada lateral del cine estaba en un callejón húmedo. James fue a la puerta y llamó. Pronto crujió y abrió un poco.



- ¿Eres limpiador? Una voz ronca vino desde adentro.



“Sí, soy yo… vine a arreglar todo.



James entró en el vestíbulo del cine. Probablemente sin otra opción, el personal comenzó a emitir boletos de papel a los visitantes. Esto dificultaba la presentación de informes financieros, y mucho menos detalles más interesantes. Pero el personal saludó a James con alivio e inmediatamente lo llevó a la sala de servidores.



A primera vista, todo estaba en orden. James inició sesión en el servidor y comprobó los lugares sospechosos habituales. No hay problema. Sin embargo, como medida de precaución, James apagó el servidor, reemplazó la NIC y revirtió el sistema. Ella instantáneamente comenzó a trabajar por completo. El personal comenzó a vender boletos nuevamente.



James llamó a Mark y le informó de la situación. No es difícil suponer que James podría querer quedarse aquí y ver si sucede algo inesperado. Bajó las escaleras y comenzó a interrogar al personal sobre lo que había sucedido. Evidentemente el sistema ha dejado de funcionar. Lo apagaron y lo encendieron, funcionó. Pero después de 10 minutos, el sistema se cayó.



Justo en ese momento sucedió algo similar. De repente, el sistema de tickets comenzó a dar errores. El personal suspiró y agarró los boletos de papel, y James se apresuró a ir a la sala de servidores. Todo se veía bien con el servidor.



Entonces entró uno de los empleados.



- El sistema está funcionando nuevamente.



James estaba desconcertado porque no había hecho nada. Más precisamente, nada que hiciera funcionar el sistema. Se desconectó, descolgó el teléfono y llamó al equipo de soporte de su empresa. Pronto, el mismo empleado entró en la sala de servidores.



- El sistema miente.



James miró al servidor. Un patrón interesante y familiar de formas multicolores bailaba en la pantalla: tubos que se retorcían y entrelazaban caóticamente. Todos hemos visto este protector de pantalla una vez. Fue bellamente renderizado y literalmente hipnotizado.





James presionó el botón y el patrón desapareció. Corrió a la taquilla y en el camino se encontró con el empleado que regresaba a él.



- El sistema está funcionando nuevamente.



Si puedes hacer mentalmente una palma de la mano, eso es exactamente lo que hizo James. Salvapantallas. Utiliza OpenGL. Y por tanto, durante el funcionamiento, consume todos los recursos del procesador del servidor. Como resultado, se agota el tiempo de espera de cada solicitud al servidor.



James regresó a la sala de servidores, inició sesión y reemplazó el hermoso protector de pantalla de tuberías con una pantalla en blanco. Es decir, en lugar de un salvapantallas que consume el 100% de los recursos del procesador, instalé otro que no consume recursos. Luego esperé 10 minutos para verificar mi conjetura.



Cuando James llegó al siguiente cine, se preguntó cómo explicarle a su supervisor que acababa de volar 800 km para apagar el protector de pantalla.



Choque en una fase lunar específica



Historia verdadera. Una vez hubo un error de software que dependía de la fase de la luna. Había una pequeña subrutina que se usaba comúnmente en varios programas del MIT para calcular la aproximación a la verdadera fase de la luna. GLS incorporó esta subrutina en un programa LISP que genera una cadena con marca de tiempo de casi 80 caracteres al escribir un archivo. Era muy raro que la primera línea de un mensaje fuera demasiado larga y pasara a la siguiente. Y cuando el programa leyó este archivo, maldijo. La longitud de la primera línea dependía de la fecha y hora exactas, así como de la longitud de la especificación de fase en el momento en que se imprimió la marca de tiempo. Es decir, ¡el error dependía literalmente de la fase de la luna!



Primera edición impresa del archivo de jerga(Steele-1983) contenía una muestra de dicha cadena que conducía al error descrito, pero el compositor lo "solucionó". Desde entonces se ha descrito como un "error de fase lunar".



Sin embargo, tenga cuidado con las suposiciones. Hace varios años, los ingenieros del CERN (Centro Europeo de Investigación Nuclear) encontraron errores en los experimentos llevados a cabo en el Gran Colisionador de Electrones y Positrones. Dado que las computadoras están procesando activamente la enorme cantidad de datos generados por este dispositivo antes de mostrar el resultado a los científicos, muchos han asumido que el software es de alguna manera sensible a la fase de la luna. Varios ingenieros desesperados llegaron al fondo de la verdad. ¡El error se produjo debido a un ligero cambio en la geometría del anillo de 27 km de largo debido a la deformación de la Tierra durante el paso de la Luna! Esta historia entró en el folclore de los físicos como "la venganza de Newton sobre la física de partículas" y un ejemplo de la conexión entre las leyes físicas más simples y antiguas con los conceptos científicos más avanzados.



Descargar el inodoro detiene el tren



El mejor error de hardware del que he oído hablar fue en un tren de alta velocidad en Francia. El error provocó el frenado de emergencia del tren, pero solo si había pasajeros a bordo. En todos los casos, el tren se puso fuera de servicio, se verificó, pero no se encontró nada. Luego lo enviaron de regreso a la línea e inmediatamente se detuvo de manera anormal.



Durante uno de los controles, un maquinista que viajaba en el tren fue al baño. Pronto se lavó después de sí mismo, ¡BOOM! Parada de emergencia.



El ingeniero se puso en contacto con el conductor y le preguntó:



- ¿Qué hizo antes de frenar?



- Bueno, reduje la velocidad en el descenso ...



Fue extraño, porque durante la marcha normal el tren frena en los descensos decenas de veces. El tren siguió su marcha y en el siguiente descenso el conductor advirtió:



- Voy a reducir la velocidad.



No pasó nada.



- ¿Qué hiciste con la última frenada? - preguntó el conductor.



- Bueno ... yo estaba en el baño ...



- ¡Bueno, entonces ve al baño y haz lo que hiciste cuando bajemos de nuevo!



El ingeniero fue al baño, y cuando el conductor advirtió: "Estoy frenando", tiró el agua. Por supuesto, el tren se detuvo de inmediato.



Ahora podían reproducir el problema y necesitaban encontrar la causa.



Dos minutos después, notaron que el cable de control remoto para el freno motor (el tren tenía un motor en ambos extremos) estaba desconectado de la pared del gabinete eléctrico y estaba en el relé que controlaba el solenoide del tapón del inodoro ... Cuando el relé se encendió, interfirió en el cable del freno y en el sistema. La protección contra choques simplemente incluye el frenado de emergencia.



La puerta de entrada que odiaba a FORTRAN



Hace unos meses notamos que las conexiones de red en el continente [esto fue en Hawai] se estaban volviendo muy, muy lentas. Podría durar de 10 a 15 minutos y luego reaparecer repentinamente. Después de un tiempo, un colega mío se quejaba de que las conexiones de red en el continente fueron no funciona en absoluto. Tenía algo de código FORTRAN que necesitaba ser copiado en una máquina en el continente, pero no funcionó porque "la red no duró lo suficiente para completar la descarga FTP".



Sí, resultó que se produjeron fallas en la red cuando un colega intentó enviar por FTP el archivo fuente de FORTRAN a una máquina en el continente. Intentamos archivar el archivo: luego se copió silenciosamente (pero no había un desempaquetador en la máquina de destino, por lo que el problema no se resolvió). Finalmente, "dividimos" el código FORTRAN en trozos muy pequeños y los enviamos uno a la vez. La mayoría de los fragmentos se copiaron sin problemas, pero algunos de ellos no funcionaron, o lo hicieron después de numerosos intentos.



Después de examinar los fragmentos del problema, encontramos que tienen algo en común: todos contienen bloques de comentarios que comienzan y terminan con líneas formadas por letras C mayúsculas (como un colega prefirió comentar en FORTRAN). Enviamos correos electrónicos al continente a los especialistas en redes y les pedimos ayuda. Por supuesto, querían ver muestras de nuestros archivos que no se podían enviar a través de FTP ... pero nuestras cartas no les llegaron. Finalmente, se nos ocurrió una descripción simple de cómo se ven los archivos no reenviados. Funcionó :) [¿Me atrevo a agregar aquí un ejemplo de uno de los comentarios problemáticos sobre FORTRAN? ¡Probablemente no valga la pena!]



Al final logramos resolverlo. Recientemente se instaló una nueva puerta de enlace entre nuestra parte del campus y la red continental. ¡Tuvo una GRAN dificultad para transmitir paquetes que contenían C mayúsculas duplicadas! Solo unos pocos de estos paquetes podrían tomar todos los recursos de la puerta de enlace y evitar que la mayoría de los otros paquetes se rompan. Nos quejamos con el fabricante de la puerta de enlace ... y nos dijeron: “¡Oh, sí, se encontró con un error C duplicado! Ya sabemos de él ". Al final, resolvimos el problema comprando un nuevo gateway de otro fabricante (en defensa del primero, diré que la imposibilidad de transferir programas a FORTRAN para alguien puede ser una ventaja).



Tiempos difíciles



Hace varios años, mientras trabajaba en un sistema Perl ETL diseñado para reducir el costo de los ensayos clínicos de fase 3, necesitaba procesar alrededor de 40.000 fechas. Dos de ellos no pasaron la prueba. Esto no me molestó demasiado, porque estas fechas fueron tomadas de los datos proporcionados por el cliente, lo que a menudo era, digamos, sorprendente. Pero cuando verifiqué los datos iniciales, resultó que estas fechas eran el 1 de enero de 2011 y el 1 de enero de 2007. Pensé que el error estaba en el programa que acabo de escribir, pero resultó que ya tenía 30 años. Esto puede parecer misterioso para quienes no estén familiarizados con el ecosistema del software. Debido a una decisión de otra empresa de ganar dinero desde hace mucho tiempo, mi cliente me pagó para solucionar un error que una empresa introdujo accidentalmente y otra intencionalmente. Para que entiendas de qué se trata,Necesito contarles sobre la compañía que agregó la función que se convirtió en un error como resultado, así como algunos otros eventos curiosos que contribuyeron al misterioso error que solucioné.



En los buenos tiempos, las computadoras Apple a veces restablecían espontáneamente su fecha al 1 de enero de 1904. La razón era simple: se usó un "reloj del sistema" a batería para realizar un seguimiento de la fecha y la hora. ¿Qué pasó cuando se agotó la batería? Las computadoras comenzaron a rastrear la fecha por el número de segundos desde el comienzo de la era. La época significaba la fecha original de referencia, y para Macintosh fue el 1 de enero de 1904. Y después de que se agotó la batería, la fecha actual se restableció a la especificada. Pero, ¿por qué sucedió esto?



Anteriormente, Apple usaba 32 bits para almacenar la cantidad de segundos desde la fecha original. Un bit puede almacenar uno de dos valores: 1 o 0. Dos bits pueden almacenar uno de cuatro valores: 00, 01, 10, 11. Tres bits: un valor de ocho: 000, 001, 010, 011, 100, 101, 110, 111, etc. Y 32 podría almacenar uno de los 2 32 valores, es decir, 4 294 967 296 segundos. Para las fechas de Apple, esto tenía aproximadamente 136 años, por lo que las Mac más antiguas no pueden manejar fechas posteriores a 2040. Y si la batería del sistema se agota, la fecha se restablece a 0 segundos desde el comienzo de la época, y debe configurar manualmente la fecha cada vez que enciende la computadora (o hasta que compre una batería nueva).



Sin embargo, la decisión de Apple de almacenar las fechas como segundos desde el comienzo de la época significó que no pudimos manejar fechas anteriores al comienzo de la época, lo que tuvo implicaciones de gran alcance, como veremos. Apple introdujo una característica, no un error. Entre otras cosas, esto significaba que el sistema operativo Macintosh era inmune al "error del milenio" (que no se puede decir de muchas aplicaciones Mac que tenían sus propios sistemas de fechas para eludir las restricciones).



Siga adelante. Usamos Lotus 1-2-3, la "aplicación asesina" desarrollada por IBM que ayudó a lanzar la revolución de las PC, aunque las computadoras Apple tenían VisiCalc, que hizo que las computadoras personales fueran exitosas. Para ser justos, si no hubiera aparecido 1-2-3, las PC difícilmente habrían despegado y la historia de las computadoras personales podría haberse desarrollado de manera muy diferente. Lotus 1-2-3 trató incorrectamente 1900 como un año bisiesto. Cuando Microsoft lanzó su primera hoja de cálculo Multiplan, tenía una pequeña participación de mercado. Y cuando lanzamos el proyecto de Excel, decidimos no solo copiar el esquema de nomenclatura de filas y columnas de Lotus 1-2-3, sino también garantizar la compatibilidad con errores, tratando deliberadamente 1900 como un año bisiesto. Este problema persiste hasta el día de hoy. Es decir, en 1-2-3 fue un error, y en Excel fue una decisión deliberada que garantizóque todos los usuarios 1-2-3 pueden importar sus hojas de cálculo a Excel sin cambiar los datos, incluso si están equivocados.



Pero había otro problema. Microsoft lanzó por primera vez Excel para Macintosh, que no reconoció fechas hasta el 1 de enero de 1904. Y en Excel, el comienzo de una era fue el 1 de enero de 1900. Por lo tanto, los desarrolladores hicieron un cambio para que su programa reconozca el tipo de época y almacene datos dentro de sí mismo de acuerdo con la época deseada. Microsoft incluso escribió un artículo explicativo sobre esto. Y esta decisión provocó mi error.



Mi sistema ETL recibió hojas de cálculo de Excel de clientes que se crearon en Windows pero también se podían crear en una Mac. Por lo tanto, el comienzo de una era en la tabla podría ser el 1 de enero de 1900 o el 1 de enero de 1904. ¿Cómo averiguarlo? El formato de archivo de Excel muestra la información necesaria, pero el analizador que usé no se mostró (ahora sí), y asumió que conoce la era de una tabla en particular. Probablemente podría haber pasado más tiempo entendiendo el binario de Excel y enviando el parche al autor del analizador, pero tenía mucho que hacer por el cliente, así que rápidamente escribí una heurística para determinar la época. Fue sencillo.



En Excel, la fecha del 5 de julio de 1998 se puede representar en el formato "07-05-98" (sistema estadounidense inútil), "5 de julio de 98", "5 de julio de 1998", "5 de julio de 1998" o en algunos otro formato inútil (irónicamente, uno de los formatos que mi versión de Excel no ofrecía era el estándar ISO 8601). Sin embargo, dentro de la tabla, la fecha sin formato se almacenó como "35981" para época-1900 o "34519" para época-1904 (los números representan el número de días desde el comienzo de la época). Solo estaba usando un analizador simple para extraer el año de la fecha formateada y luego usando el analizador de Excel para extraer el año de la fecha sin formato. Si ambos valores diferían en 4 años, entonces entendí que estaba usando un sistema con epoch-1904.



¿Por qué no utilicé fechas formateadas? Porque el 5 de julio de 1998 se puede formatear como "julio de 98" sin el día del mes. Recibimos tablas de tantas empresas que las crearon de formas tan diferentes que nosotros (en este caso, yo) tuvimos que lidiar con las fechas. Además, si Excel lo hace bien, ¡nosotros también deberíamos hacerlo!



Luego me encontré con 39082. Permítanme recordarles que Lotus 1-2-3 consideraba que 1900 era un año bisiesto, y esto se repitió fielmente en Excel. Y dado que esto agregó un día a 1900, muchas de las funciones de fecha podrían estar incorrectas para ese mismo día. Es decir, 39082 podría haber sido el 1 de enero de 2011 (en Mac) o el 31 de diciembre de 2006 (en Windows). Si mi "analizador de años" extraía 2011 del valor formateado, entonces todo está bien. Pero como el analizador de Excel no sabe qué época usar, por defecto es epoch-1900, devolviendo 2006. Mi aplicación vio que había una diferencia de 5 años, lo consideró un error, registró y devolvió un valor sin formato.



Para evitar esto, escribí esto (pseudocódigo):



diff = formatted_year - parsed_year
if 0 == diff
    assume 1900 date system
if 4 == diff
    assume 1904 date system
if 5 == diff and month is December and day is 31
    assume 1904 date system


Y luego las 40,000 fechas se analizaron correctamente.



En medio de grandes trabajos de impresión



A principios de la década de 1980, mi padre trabajaba en Storage Technology, una unidad comercial extinta que construía unidades de cinta y sistemas neumáticos para la alimentación de cinta de alta velocidad.



Rediseñaron las unidades para que pudieran tener una unidad central "A" conectada a siete unidades "B", y el pequeño sistema operativo en la RAM que controlaba la unidad "A" podía delegar las operaciones de lectura y escritura en todas las unidades "B".



Cada vez que se iniciaba la unidad "A", se tenía que insertar un disquete en la unidad periférica conectada a "A" para cargar el sistema operativo en su memoria. Era extremadamente primitivo: la potencia de procesamiento la proporcionaba un microcontrolador de 8 bits.



El público objetivo de dicho equipo eran empresas con grandes almacenes de datos (bancos, cadenas minoristas, etc.) que necesitaban imprimir muchas etiquetas de dirección o extractos bancarios.



Un cliente tuvo un problema. En medio de un trabajo de impresión, una unidad "A" en particular podría dejar de funcionar, provocando que todo el trabajo se levante. Para que la unidad volviera a funcionar, el personal tuvo que reiniciar todo. Y si esto sucedía en medio de una tarea de seis horas, se desperdiciaba una gran cantidad de tiempo de computadora costoso y se interrumpía el cronograma de toda la operación.



Storage Technologies envió técnicos. A pesar de sus mejores esfuerzos, no pudieron reproducir el error en condiciones de prueba: parece que el bloqueo se produjo en medio de grandes trabajos de impresión. El problema no era el hardware, reemplazaron todo lo que pudieron: RAM, microcontrolador, disquetera, cada parte imaginable de una unidad de cinta - el problema persistió.



Luego, los técnicos llamaron a la sede y llamaron al Experto.



El examinador tomó una silla y una taza de café, se sentó en la sala de computadoras (en aquellos días había salas dedicadas a las computadoras) y observó cómo el personal hacía cola para un gran trabajo de impresión. El experto esperó a que ocurriera una falla, y eso sucedió. Todos miraron al Experto, y él no tenía idea de por qué sucedió esto. Por lo tanto, ordenó que la tarea se volviera a poner en cola y todos los empleados con técnicos volvieron a trabajar.



El experto volvió a sentarse en su silla y esperó el fallo. Tomó alrededor de seis horas y se produjo la falla. El Experto nuevamente no tenía ideas, excepto que todo sucedió en una habitación llena de gente. Ordenó reiniciar la misión, volvió a sentarse y esperó.



A la tercera falla, el experto notó algo. La falla ocurrió cuando el personal cambió las correas en una unidad externa. Además, el accidente ocurrió tan pronto como uno de los empleados atravesó cierta baldosa en el piso.



El piso elevado estaba hecho de baldosas de aluminio colocadas de 6 a 8 pulgadas de alto. Numerosos cables de computadora corrían debajo del piso elevado para que alguien no pisara accidentalmente un cable importante. Las baldosas se colocaron muy apretadas para que no pudieran entrar escombros debajo del piso elevado.



El experto se dio cuenta de que una de las tejas estaba deformada. Cuando un empleado pisó su esquina, el azulejo frotó sus bordes contra los azulejos adyacentes. También frotaron las piezas de plástico que conectaban las baldosas, lo que creó microdescargas estáticas que crearon interferencias de radiofrecuencia.



Hoy en día, la RAM está mucho mejor protegida contra las interferencias de radiofrecuencia. Pero en esos años no fue así. El experto se dio cuenta de que estas interferencias perturbaban la memoria y con ella el funcionamiento del sistema operativo. Llamó al servicio de escolta, pidió una baldosa nueva, la instaló él mismo y el problema desapareció.



¡Es la marea!



La historia tuvo lugar en una sala de servidores en el cuarto o quinto piso de una oficina en Portsmouth (creo), en el área del muelle.



Un día falló un servidor Unix con la base de datos principal. Se reinició, pero alegremente continuó cayendo una y otra vez. Decidimos llamar a alguien del servicio de soporte.



Amigo de apoyo ... Creo que se llamaba Mark, pero no importa ... No creo que lo conozca. Realmente no importa. Quedémonos en el Mark, ¿de acuerdo? Excelente.



Entonces, unas horas después llegó Mark (de Leeds a Portsmouth el camino no está cerrado, ya sabes), encendió el servidor y todo funcionó sin problemas. Típico apoyo de mierda, el cliente se enoja mucho por eso. Mark revisa los archivos de registro y no encuentra nada objetable. Entonces Mark vuelve al tren (o al medio de transporte que tomó, hasta donde yo sé, podría haber sido una vaca coja ... bueno, no importa, ¿de acuerdo?) Y regresa a Leeds, desperdiciando el día.



El servidor vuelve a fallar esa noche. La historia es la misma ... el servidor no sube. Mark intenta ayudar de forma remota, pero el cliente no puede iniciar el servidor.



Otro tren, autobús, merengue de limón o alguna otra mierda, y Mark está de vuelta en Portsmouth. ¡Mira, el servidor arranca sin problemas! Milagro. Mark comprueba durante varias horas que todo está en orden con el sistema operativo o el software y se dirige a Leeds.



A la mitad del día, el servidor se bloquea (¡tómatelo con calma!). Esta vez, parece prudente contratar personal de soporte de hardware para reemplazar el servidor. Pero no, después de unas 10 horas también cae.



La situación se repitió durante varios días. El servidor está activo, se bloquea después de aproximadamente 10 horas y no se inicia durante las próximas 2 horas. Revisaron enfriamiento, pérdidas de memoria, revisaron todo, pero no encontraron nada. Entonces cesaron los choques.



La semana pasó sin preocupaciones ... todos estaban felices. Feliz hasta que todo empiece de nuevo. La imagen es la misma. 10 horas de trabajo, 2-3 horas de inactividad ...



Y luego alguien (creo que me dijeron que esta persona no tenía nada que ver con eso) dijo:



"¡Esta es la marea!"



La exclamación fue recibida con miradas en blanco y, probablemente, la mano de alguien vaciló en el botón para llamar al guardia.



"Deja de trabajar con la marea".



Esto parecería un concepto completamente extraño para el personal de soporte de TI que apenas lee el Anuario de Tide mientras se sienta a tomar un café. Explicaron que no tenía nada que ver con la marea porque el servidor había estado funcionando durante una semana sin problemas.



"La marea estuvo baja la semana pasada y alta esta semana".



Un poco de terminología para aquellos que no tienen un alquiler de yates. Las mareas dependen del ciclo lunar. Y a medida que la Tierra gira, cada 12,5 horas la atracción gravitacional del Sol y la Luna crea un maremoto. Al comienzo de un ciclo de 12,5 horas, hay una marea alta, en el medio del ciclo hay una marea baja y al final de una marea alta nuevamente. Pero a medida que cambia la órbita de la luna, también cambia la diferencia entre reflujo y flujo. Cuando la Luna está entre el Sol y la Tierra o en el lado opuesto de la Tierra (luna llena o sin luna), obtenemos mareas de Syzygy: las mareas más altas y las mareas de reflujo más bajas. En la media luna tenemos mareas en cuadratura, las mareas más bajas. La diferencia entre los dos extremos se reduce considerablemente. El ciclo lunar dura 28 días: sicigia - cuadratura - sicigia - cuadratura.



Cuando se explicaron las fuerzas de la marea a los técnicos, inmediatamente pensaron en llamar a la policía. Y es bastante lógico. Pero resultó que el tipo tenía razón. Dos semanas antes, un destructor había atracado cerca de la oficina. Cada vez que la marea lo elevara a cierta altura, el puesto de radar del barco estaría al nivel del piso de la sala de servidores. Y el radar (o el equipo de guerra electrónica, o algún otro juguete militar) creó el caos en las computadoras.



Misión de vuelo para un cohete



Se me ordenó portar un gran sistema de control y monitoreo de lanzamiento de misiles (alrededor de 400 mil líneas) para nuevas versiones del sistema operativo, compilador y lenguaje. Más precisamente, desde Solaris 2.5.1 en Solaris 7, y desde Verdix Ada Development System (VADS) escrito en Ada 83 hasta el sistema Rational Apex Ada escrito en Ada 95. VADS fue comprado por Rational y su producto es obsoleto, aunque Rational intentó implementar versiones compatibles de paquetes específicos de VADS para facilitar la transición al compilador Apex.



Tres personas me ayudaron a obtener un código compilado de forma limpia. Tardaron dos semanas. Y luego trabajé por mi cuenta para que el sistema funcionara. En resumen, fue la peor arquitectura e implementación de un sistema de software que he encontrado, por lo que tomó otros dos meses completar la migración. Luego, el sistema se entregó para su prueba, lo que llevó varios meses más. Inmediatamente arreglé los errores que encontré durante las pruebas, pero su número disminuyó rápidamente (el código fuente era un sistema de producción, por lo que su funcionalidad funcionó de manera bastante confiable, solo tuve que eliminar los errores que surgieron al adaptarme al nuevo compilador). Al final, cuando todo funcionó como debía, me trasladaron a otro proyecto.



Y el viernes antes de Acción de Gracias, sonó el teléfono.



Aproximadamente tres semanas después, se iba a probar el lanzamiento de un cohete y, en las pruebas de laboratorio de la cuenta atrás, se bloqueó la secuencia de comandos. En la vida real, esto llevaría a la interrupción de las pruebas, y si se produjera un bloqueo a los pocos segundos de arrancar el motor, se producirían varias acciones irreversibles en los sistemas auxiliares, lo que llevaría mucho tiempo, y caro, volver a preparar el cohete. No comenzaría, pero mucha gente se enojaría mucho por la pérdida de tiempo y mucho dinero. No permita que nadie le diga que el Departamento de Defensa está gastando dinero de improviso; todavía tengo que conocer a un gerente de contratos que no tenga un presupuesto primero o segundo, seguido de un cronograma.



En meses anteriores, esta prueba de cuenta regresiva se había ejecutado cientos de veces en muchas variaciones, con solo algunos pequeños problemas. Entonces, la probabilidad de que esto sucediera era muy baja, pero sus consecuencias fueron muy significativas. Multiplique ambos factores y comprenderá que las noticias predijeron una semana festiva arruinada para mí y para decenas de ingenieros y gerentes.



Y me llamaron la atención como la persona que portó el sistema.



Al igual que con la mayoría de los sistemas críticos para la seguridad, aquí se registraron muchos parámetros, por lo que fue bastante fácil identificar las pocas líneas de código que se ejecutaron antes de que el sistema fallara. Y, por supuesto, no había absolutamente nada fuera de lo común en ellos, las mismas expresiones se realizaron con éxito literalmente miles de veces durante la misma ejecución.



Llamamos a la gente de Apex a Rational porque habían desarrollado el compilador y algunas de las rutinas que habían desarrollado se llamaban en el código sospechoso. Ellos (y todos los demás) quedaron impresionados por la necesidad de descubrir la causa del problema de importancia literalmente nacional.



Como no había nada interesante en los registros, decidimos intentar reproducir el problema en un laboratorio local. Esta no fue una tarea fácil ya que el evento ocurrió aproximadamente una vez cada 1000 ejecuciones. Una de las supuestas razones fue que la llamada a una función mutex desarrollada por el proveedor (parte del lote de migración de VADS)Unlockno condujo al desbloqueo. El hilo de llamada procesaba mensajes de latido, que nominalmente llegaban cada segundo. Elevamos la frecuencia a 10 Hz, es decir, 10 veces por segundo, y comenzamos a correr. Después de aproximadamente una hora, el sistema se bloqueó. En el registro, vimos que la secuencia de mensajes grabados era la misma que durante la prueba fallida. Hicimos algunas carreras más, el sistema se bloqueó de manera estable 45-90 minutos después del inicio, y cada vez el registro contenía la misma pista. A pesar del hecho de que técnicamente estábamos ejecutando un código diferente ahora, la tasa de mensajes era diferente, el comportamiento del sistema se repitió, por lo que nos aseguramos de que este escenario de carga condujera al mismo problema.



Ahora era necesario averiguar exactamente en qué lugar de la secuencia de expresiones se produjo el bloqueo.



Esta implementación utilizó el sistema de tareas Ada y fue increíblemente mal utilizada. Las tareas son una construcción de alto nivel, ejecutable simultáneamente en Ada, algo así como hilos de ejecución, simplemente integrados en el lenguaje mismo. Cuando dos tareas necesitan interactuar, se "encuentran", intercambian los datos necesarios y luego detienen la cita y regresan a sus actuaciones independientes. Sin embargo, el sistema se implementó de manera diferente. Después de que un objetivo tuviera un encuentro, ese objetivo se encontraría con otro, que luego se encontraría con un tercero, y así sucesivamente, hasta que se completara algún procesamiento. Después de eso, todos estos encuentros terminaron y cada tarea tuvo que volver a su ejecución. Es decir, estábamos tratando con el sistema de llamada a funciones más caro del mundo,que detuvo todo el proceso de "multitarea" mientras procesaba algunos de los datos de entrada. En el pasado, esto no generaba problemas solo porque el rendimiento era muy bajo.



Describí este mecanismo de tareas porque cuando se solicitaba una cita o se esperaba que se completara, podía ocurrir un "cambio de tarea". Es decir, el procesador podría comenzar a procesar otra tarea lista para ejecutarse. Resulta que cuando una tarea está lista para encontrarse con otra tarea, puede comenzar la ejecución de una tarea completamente diferente y, finalmente, el control vuelve al primer encuentro. Y pueden ocurrir otros eventos que lleven a un cambio de tarea; uno de estos eventos es una llamada a una función del sistema, como imprimir o ejecutar un mutex.



Para comprender qué línea de código estaba causando el problema, necesitaba encontrar una manera de registrar el progreso de la secuencia de expresiones sin activar un cambio de tarea, lo que podría evitar que ocurriera el bloqueo. Entonces no pude aprovecharPut_Line()para no realizar operaciones de E / S. Puede establecer una variable de contador o algo así, pero ¿cómo puedo ver su valor si no puedo mostrarlo en la pantalla?



Además, al examinar el registro, resultó que, a pesar de la congelación del procesamiento de los mensajes de latido, que bloqueó todas las operaciones de E / S del proceso y no permitió que se realizaran otros procesos, se continuaron ejecutando otras tareas independientes. Es decir, el trabajo no se bloqueó por completo, solo la cadena (crítica) de tareas.



Este fue el gancho requerido para evaluar la expresión de bloqueo.



Hice un paquete Ada que contenía una tarea, un tipo enumerado y una variable global de ese tipo. Literales enumerados fueron atados a expresiones específicas secuencias problemáticas (por ejemplo Incrementing_Buffer_Index, Locking_Mutex,Mutex_Unlocked) y luego insertó expresiones de asignación en él, que asignaron la enumeración correspondiente a una variable global. Dado que el código objeto de todo esto simplemente se mantuvo constante en la memoria, el cambio de tareas como resultado de su ejecución era extremadamente improbable. En primer lugar, sospechamos expresiones que podrían cambiar la tarea, ya que el bloqueo se produjo durante la ejecución y no regresaba al cambiar la tarea (por varias razones).



La tarea de seguimiento simplemente se ejecutó en un bucle y se verificó periódicamente para ver si el valor de la variable global había cambiado. Con cada cambio, el valor se guardaba en un archivo. Luego, una breve espera y un nuevo cheque. Escribí la variable en un archivo porque la tarea se ejecutó solo cuando el sistema la seleccionó para su ejecución al cambiar la tarea en el área del problema. Pase lo que pase en esta tarea no afectará a otras tareas bloqueadas no relacionadas.



Se esperaba que cuando el sistema alcanzara la ejecución del código problemático, la variable global se restablecería con cada siguiente expresión. Entonces sucederá algo que provocará un cambio de la tarea, y dado que la frecuencia de su ejecución (10 Hz) es menor que la de la tarea de monitoreo, el monitor podría fijar el valor de la variable global y escribirlo. En una situación normal, podría obtener una secuencia repetida de un subconjunto de enumeraciones: los últimos valores de la variable en el momento del cambio de tarea. Cuando se cuelga, la variable global ya no debería cambiar, y el último valor escrito mostrará qué expresión no completó la ejecución.



Lanzó el código de seguimiento. Esta congelado. Y el seguimiento funcionó como un reloj.



El registro terminó con la secuencia esperada, que fue interrumpida por un valor que indica que se llamó al mutex Unlocky la tarea estaba pendiente, como fue el caso de miles de llamadas anteriores.



Los ingenieros de Apex en este momento analizaron frenéticamente su código y encontraron un lugar en el mutex donde, en teoría, podría ocurrir un bloqueo. Pero su probabilidad era muy pequeña, ya que solo una cierta secuencia de eventos que ocurrieran en un momento determinado podía provocar un bloqueo. Muchachos de la ley de Murphy, es la ley de Murphy.



Para proteger este fragmento de código, reemplacé las llamadas a las funciones mutex (construidas sobre la funcionalidad mutex del sistema operativo) con un pequeño paquete nativo de mutex Ada para controlar el acceso mutex a ese fragmento.



Lo pegué en el código y ejecutó la prueba. Siete horas después, el código siguió funcionando.



Mi código fue transferido a Rational, donde fue compilado, desensamblado y verificado que no usa el mismo enfoque que se usó en las funciones de mutex problemáticas.



Fue la revisión de código más concurrida de mi carrera :) Había unos diez ingenieros y gerentes en la sala conmigo, una docena de personas más conectadas en una conferencia telefónica, y todos examinaron unas 20 líneas de código.



Se revisó el código, se crearon nuevos archivos ejecutables y se enviaron para pruebas de regresión formales. Un par de semanas después, las pruebas de la cuenta regresiva fueron exitosas y el cohete despegó.



Está bien, todo esto es bueno y hermoso, pero ¿cuál es el sentido de esta historia?



Fue un problema totalmente repugnante. Cientos de miles de líneas de código, ejecución paralela, más de una docena de procesos interactivos, arquitectura deficiente e implementación deficiente, interfaces para sistemas integrados y millones de dólares gastados. Sin presión, cierto.



No era el único que trabajaba en este tema, aunque estaba en el centro de atención mientras realizaba la migración. Pero a pesar de que lo hice, esto no significa que descubrí los cientos de miles de líneas de código, o al menos las hojeé. El código y los registros fueron analizados por ingenieros de todo el país, pero cuando me contaron sus hipótesis sobre las causas de la falla, me tomó medio minuto refutarlas. Y cuando me pidieron que analizara las teorías, se lo pasé a otra persona, porque era obvio para mí que estos ingenieros iban por el camino equivocado. ¿Suena presuntuoso? Sí, lo es, pero rechacé hipótesis y solicitudes por una razón diferente.



Entendí la naturaleza del problema. No sabía exactamente dónde estaba ni por qué, pero sabía exactamente lo que estaba pasando.



A lo largo de los años, he acumulado muchos conocimientos y experiencia. Fui uno de los pioneros en usar Ada, entendí sus ventajas y desventajas. Sé cómo las bibliotecas de tiempo de ejecución de Ada manejan las tareas y se ocupan de la ejecución en paralelo. Y soy bueno en la programación de bajo nivel a nivel de memoria, registros y ensamblador. En otras palabras, tengo un conocimiento profundo en mi campo. Y los usé para encontrar la causa del problema. No solo solucioné el error, sino que descubrí cómo encontrarlo en un entorno de ejecución muy sensible.



Tales historias de lucha con el código no son muy interesantes para aquellos que no están familiarizados con las peculiaridades y condiciones de tal lucha. Pero estas historias ayudan a comprender qué se necesita para resolver problemas realmente difíciles.



Necesita ser más que un simple programador para resolver problemas realmente difíciles. Es necesario comprender el "destino" del código, cómo interactúa con su entorno y cómo funciona el entorno en sí.



Y luego tienes tu semana de vacaciones estropeada.






Continuará.



All Articles