La Singularidad Desnuda

Un universo impredecible de pensamientos y cavilaciones sobre ciencia, tecnología y otros conundros

Un fallo de punteros acabó con la Mars Global Surveyor

Posted by Carlos en abril 14, 2007

Cuando hace poco más de cinco meses la Mars Global Surveyor perdió contacto con la Tierra, La NASA formó un comité interno para estudiar las causas. Los resultados del informe se hicieron públicos ayer mismo, reconstruyendo la cadena de eventos que dieron lugar a la pérdida final de la sonda. A grandes rasgos, el error crítico que desencadenó todo fue un fallo en la escritura en memoria de la nave, que tuvo lugar al intentar corregir un error no-crítico anterior. Básicamente, la situación fue la siguiente:

  • Los sistemas de la nave están deseñados con redundancia, precisamente para hacerla más robusta ante posibles fallos de equipamiento o de programación. Así por ejemplo, los parámetros de control de la sonda se almacenan por duplicado, y cualquier inconsistencia entre las dos copias dispara una alerta de seguridad. Uno de estos parámetros hace referencia a la orientación de una de las antenas de la sonda (HGA), y se actualizó en septiembre de 2005 en dos momentos diferentes cada una de las dos copias. Durante este proceso, los datos se introdujeron con diferente precisión en cada ocasión. La diferencia era en la práctica irrelevante y no conllevaba ningún peligro, pero fue detectada por los sistemas de seguridad por lo que fue necesaria una actualización en junio de 2006. Durante la misma tuvo lugar el error crítico: el valor corregido se escribió en una dirección de memoria incorrecta. Esto afectó a los límites de seguridad de los paneles solares, y corrompió la dirección en la que debía apuntar la HGA durante una contingencia.
  • En noviembre de 2006 se mandaron instrucciones rutinarias a la sonda para reposicionar uno de sus paneles solares, pero la corrupción en el límite de seguridad hizo que el panel girará hasta el límite físico. En ese momento, la sonda interpretó que uno de los paneles estaba atascado por lo que entró en modo de contingencia con tan mala fortuna que una de las baterías quedó expuesta directamente al Sol. Dicha batería se sobrecalentó, lo que fue nuevamente erróneamente interpretado como una sobrecarga, lo que condujo a que se interrumpiera su recarga, y se pasara a la batería de reserva. Ésta no pudo soportar toda la carga eléctrica de la sonda, por lo que en un plazo de 12 horas ambas baterías se descargaron completamente.
  • Aunque la sonda esta orientada correctamente hacia la Tierra, la dirección en la que la HGA debía apuntar en ese caso estaba corrompida, por lo que fue imposible la comunicación con el equipo de seguimiento en tierra, y la detección de las falsas alarmas.

Como puede verse, la cadena de eventos fue realmente desafortunada, y aunque se parte de un fallo de programación, el informe de la NASA afirma que se siguieron los protocolos y procedimientos correctamente. No se culpa directamente a la reducción del presupuesto, pero sí se dice que con más medios quizás hubieran sido posibles revisiones periódicas que hubieran detectado el fallo antes de que se produjera.

Mars Global Surveyor

Sea como fuere, este lamentable accidente pone fin a una misión de 10 años, cinco veces más de los dos años iniciales planeados. Fue precisamente el valor científico de los datos proporcionados por la sonda lo que motivó que se extendiera tanto la misión. Cuando se habla de sacarle valor al dinero invertido en el programa espacial, sin duda esta misión ha de ser uno de los ejemplos. Al margen de esto, hay una moraleja doble para los estudiantes de informática: (1) hasta los ingenieros de la NASA comenten errores con los punteros, y (2) si queremos algún día conquistar el espacio, ¡estudia bien los punteros for favor!

Enviar a Blog Memes Enviar a del.icio.us Enviar a digg Enviar a fresqui Enviar a menéame

21 respuestas to “Un fallo de punteros acabó con la Mars Global Surveyor”

  1. Juan David said

    Increible que un pequeño error desencadene una serie de acontecimientos que terminan en el fin de una misión tan compleja.

  2. eulez said

    Sobre la moraleja doble para los estudiantes de informática, hay una tercera: «no utilices punteros, cámbiate a Java». Un saludo.

  3. Carlos said

    Bueno, sería «cámbiate a java y utiliza punteros sin darte cuenta» 😉 . Saludos.

  4. Carlos said

    Juan David, hay varios antecedentes similares en la historia de la carrera espacial (Mariner I, Ariane 5, Mars Climate Orbiter, …). Es realmente lamentable la cantidad de esfuerzo y recursos que se pueden ir al traste en unos segundos por una tontería de éstas.

  5. GDFH said

    Se suponen que trabajan los mejores, en una misión que vale miles de millones seguramente. No tienen vergüenza. No es la primera vez que pasa algo con la programación y demás historias.

  6. Villa said

    Al comentario de GDFH me gustaría agregarle una famosa frase «el software es la creación más compleja de la humanidad». Los soft de las naves espaciales son únicos y como bien sabréis por muchas pruebas que se hagan (Windows es un ejemplo) siempre hay algo que no has probado (y la Ley de Murphy no perdona). Sí, es verdad, los que trabajan son muy buenos (casi los mejores), pero chequear si un programa de miles de líneas funciona «correctamente», con los conocimientos actuales de la informática es imposible, en el caso general, y muy difícil y costoso en la práctica. En «una misión que vale miles de millones», normalmente se «tiene en cuenta» sólo el hard, y se olvida que el software vale mucho dinero. Quizás duplicando el presupuesto, fifty-fifty, hard-soft, muchos de estos errores no se producirían, pero … quién está dispuesto a duplicar el presupuesto.

  7. Error500 said

    La semana en los blogs LXXII

  8. iabal said

    Yo soy estudiante de Ingeniería Informática… y si algún día tuviese que enfrentarme a un proyecto de esas características (realmente por mí lo haría en cualquier proyecto) ni usaría lenguajes con punteros, ni usaría Java. Usaría un lenguaje funcional 🙂 Si fuera la NASA quizás aportaría dinero en investigaciones sobre lenguajes funcionales y verificación formal (que existe, está semiautomatizada, pero requiere más trabajo hacerla totalmente o casi totalmente automática). Y esto de la verificación formal en un lenguaje funcional puede ser dificil, pero en un lenguaje como Java directamente es un infierno.

    Mi mensaje a los estudiantes de I. I. como yo es: Deberíamos hacer lo posible por conseguir un software libre de errores y eso no se consigue programando en Java y rechazando los lenguajes funcionales. Los lenguajes funcionales son más dificiles de aprender, porque tienen una base matemática muy fuerte (sobre todo Haskell) pero se supone que somos in-ge-nie-ros, y se supone que las matemáticas que estudias en 1º, en 2º, en 3º, en 4º (en fin, en toda la carrera) sirven para algo. Si luego resulta que somos como cualquier aficionado que aprende Java en su casa, que le quitan los while y los for y se pierde, que no sabe expresar lo que debe hacer un programa en un lenguaje matemático-formal, ¡¡¡mal vamos!!!

    Aunque no es la dirección en la que yo creo que se debería mover esto (no lo explico porque no quiero extenderme demasiado) existe un entorno de programación llamado Coq, desarrollado por el INRIA, en el que, resumiendo, programas en un lenguaje formal a la vez que demuestras la correción de tu código y luego tienes la posibilidad de traducirlo a OCaml o a Haskell.

  9. Sin duda cuando se trabajo con punteros hay que revisar el trabajo 3 veces y estudiar bien los parametros, aun con el riesgo de que los cabrones te traicionen 😛

  10. cua said

    Es lo que pasa cuando se lanza al espacio una nave en 2006 con tecnología de 1973 (programas escritos en C usando punteros, suponiendo que ese haya sido el problema). Lo que en otros campos se interpretaría como una barbaridad, en ingeniería del software es tristemente habitual.

  11. Un comando equivocado se confirma como origen de la pérdida de la Mars Global Surveryor

    Tal y como se sospechaba desde hace ya algún tiempo, el equipo que investiga la pérdida de la sonda Mars Global Surveyor de la NASA ha confirmado este pasado viernes que un error de programación fue el que puso en…

  12. Carlos said

    No sé exactamente en qué lenguaje estaba todo programado, pero al hilo del uso de tecnología un tanto obsoleta, me consta que en determinados ámbitos en los que la seguridad es crítica se usan a veces programas escritos en dialectos antiguos. El motivo es que este tipo de software requiere una serie de certificaciones por parte de los organismos competentes, y esto es costoso de obtener debido a todos los exámenes por los que ha de pasar el código. Así, si se obtuvo en su momento, se puede preferir parchearlo (con cuidado de no tocar las partes críticas que harían perder la certificación) en lugar de actualizarlo a un lenguaje moderno.

  13. elmanytas said

    Estamos hablando de que ese lenguaje de programación en realidad interacciona directamente con el hardware.
    ¿Como haces eso si no es con C o con ensamblador?

    ¿Con java que funciona dentro de una máquina virtual? ¿Como escribes en una dirección de memoria o en un registro del procesador usando java? NO SE PUEDE
    ¿Con programación funcional? ¿Te haces tu un compilador para ese hardware que funcione de forma funcional?

    C es un lenguaje que funciona perfectamente y en el que están escrito software tan robusto como los núcleos de todos los sistemas operativos.

    Y otra cosa. C no es difícil. Solo hay que andarse con un poco de cuidado.

    Muchas veces no parece que seamos conscientes de que java, .net, … por debajo se compilan usando C así que a lo mejor no es tan malo.

  14. elmanytas said

    El mundo está escrito en C.

  15. Danielito said

    Moraleja: Hasta los super »inteligentes» ingenieros de la NASA, pueden cometer fallos de principiantes en la programacion de punteros.

  16. cennc said

    Lo que hay que tener siempre en cuenta es esto:
    «Las pruebas pueden demostrar la presencia de errores, pero no su ausencia»
    Edsger Dijkstra

  17. iabal said

    Elmanytas, no quiero crear un flame y menos aqui pero me veo en la obligación de responderte:

    ¿Como haces C sin ensamblador?
    ¿Como haces un ensamblador?

    «¿Con programación funcional? ¿Te haces tu un compilador para ese hardware que funcione de forma funcional?»
    ¿Haces tu el compilador de C en ensamblador para ese hardware?

    «C es un lenguaje que funciona perfectamente y en el que están escrito software tan robusto como los núcleos de todos los sistemas operativos.»

    C es un lenguaje que funciona perfectamente siempre que se use correctamente, y eso no es cierto en el 99,9999% de los casos. Y no porque los programadores sean malos, sino porque C es un lenguaje que ayuda muy poco a hacer programas robustos.

    ¿Cuantos errores realmente criticos existen o existieron en programas muy conocidos que consistian en un simple desbordamiento de buffer -o cosas más simples-? ¿Eres consciente que una instruccion tan simple de C como strcpy puede ser explotada para provocar un buffer overflow?

    ¿Sabes que puede pasar si en uno de tus ultra-robustos programas escritos en C cambiar un == por un =?
    Yo sí sé que es lo que va a pasar en cualquier lenguaje funcional: error de compilación.

    «Y otra cosa. C no es difícil. Solo hay que andarse con un poco de cuidado.»

    Cuando programas en C tienes que estar tan tan atento a no cometer ninguna pifia con los punteros o con escribir en zonas de memoria que no te corresponden cuando manejas cadenas de caracteres etc etc, que al final pasas más tiempo buscando posibles errores que pensando en hacer buenos algoritmos.

    «Muchas veces no parece que seamos conscientes de que java, .net, … por debajo se compilan usando C así que a lo mejor no es tan malo.»

    Muchas veces no parece que seamos conscientes de que C existe gracias al ensamblador, asique programar en ensamblador no debe ser tan malo.

    Muchas veces no parece que seamos conscientes que de la calidad de un código pueden depender la vida de muchas personas, o enormes cantidades de trabajo y presupuesto.

    Cennc: Por eso el único camino hacia la perfección es la Verificación Formal + lenguajes funcionales 😉

  18. elmanytas said

    «Elmanytas, no quiero crear un flame y menos aqui pero me veo en la obligación de responderte:»
    Los flames son buenos siempre que se apoyen en motivos técnicos. Las «discusiones» son buenas para internet.

    «¿Como haces C sin ensamblador?
    ¿Como haces un ensamblador?»
    Para hacer un ensamblador sustituyes los códigos de operación del micro que estés usando por palabras más fáciles de recordar. Recordar que «add» sirve para sumar es más fácil de recordar que «00101011» por ejemplo sirve para sumar. Eso ya lo tienen hecho … a menos que tengan una memoria fuera de lo normal.
    Luego traduces a = a + 1 por add,a,a,1 y listo.
    A la hora de hacer un bucle o cualquier construcción, la estructura del propio C es bastante cercana al ensamblador por lo que hacer un compilador de C para ese ensamblador es relativamente sencillo.

    «“¿Con programación funcional? ¿Te haces tu un compilador para ese hardware que funcione de forma funcional?”
    ¿Haces tu el compilador de C en ensamblador para ese hardware?»
    aver, perdona mi desconocimiento ¿como se hace en programación funcional que en la posición de memoria 3 se escriba el número 5?
    Yo se que en C es así:
    int *posicion;
    posicion = 3;
    *posicion = 5;
    ¿Como se hace esto en un lenguaje de programación funcional?

    «C es un lenguaje que funciona perfectamente siempre que se use correctamente, y eso no es cierto en el 99,9999% de los casos. Y no porque los programadores sean malos, sino porque C es un lenguaje que ayuda muy poco a hacer programas robustos.»
    Pero por el contrario permiten el control absoluto del hardware que haya por debajo. Por eso se usa en sistemas operativos. Y de sistemas operativos estamos hablando: el sistema operativo de la sonda.

    «¿Cuantos errores realmente criticos existen o existieron en programas muy conocidos que consistian en un simple desbordamiento de buffer -o cosas más simples-? ¿Eres consciente que una instruccion tan simple de C como strcpy puede ser explotada para provocar un buffer overflow?»
    Perfectamente consciente. De hecho he provocado muchos.
    Dime como copiar la cadena «abcd» a la posición de memoria 3 sin arriesgarte a un buffer overflow usando programación funcional y sin hacer algo así (puede que me equivoque en la sintaxis porque hace mucho que no programo en C):
    cadena **datos;
    cadena = 3;
    strcpy(cadena, «abcd»);

    «¿Sabes que puede pasar si en uno de tus ultra-robustos programas escritos en C cambiar un == por un =?
    Yo sí sé que es lo que va a pasar en cualquier lenguaje funcional: error de compilación.»
    Vamos, que un lenguaje de programación funcional no te da la posibilidad de hacerlo. ¿no? Pues estás tirando a la basura algunas de las instrucciones del microprocesador.
    Si tu lenguaje de programación habitual es C, jamás se te ocurre cambiar un == por un = porque sabes perfectamente que hace cada cosa.

    «Cuando programas en C tienes que estar tan tan atento a no cometer ninguna pifia con los punteros o con escribir en zonas de memoria que no te corresponden cuando manejas cadenas de caracteres etc etc, que al final pasas más tiempo buscando posibles errores que pensando en hacer buenos algoritmos.»
    Insisto: hay que manejar zonas de memoria cuando se hacen sistemas operativos. Me da igual que no te guste usarlas. Si no te gusta a lo mejor lo tuyo es hacer algoritmos matemáticos, o ventanitas, u otra cosa … pero no un sistema operativo.
    Las máquinas se manejan con instrucciones, registros, direcciones de memoria … y no se le puede decir «ponme el panel en este angulo». Hay que escribir el ángulo en la posición de memoria tal. No hay más remedio.

    «Muchas veces no parece que seamos conscientes de que C existe gracias al ensamblador, asique programar en ensamblador no debe ser tan malo.»
    Y para muchas cosas es fundamental. De hecho parte del código del sistema operativo está escrito en ensamblador.

    «Muchas veces no parece que seamos conscientes que de la calidad de un código pueden depender la vida de muchas personas, o enormes cantidades de trabajo y presupuesto.»
    Perfectamente consciente. Por eso se hacen distintos lenguajes de programación adaptados a cada necesidad.
    El error está en querer usar el mismo para todas las cosas. php está para programación web, perl para administración de sistemas, c para desarrollo a bajo nivel, java y mono para desarrollo a alto nivel multiplataforma de casi todo … si te sobran recursos, python y ruby para desarrollo a alto nivel y administración de sistemas … programación funcional ¿para hacer un sistema operativo? Creo que no es su ámbito. La programación funcional es perfecta para otros ámbitos pero no en este.

    «Cennc: Por eso el único camino hacia la perfección es la Verificación Formal + lenguajes funcionales ;)»
    No dudo que eso sea cierto en el mundo de las ideas de Platón, pero en el mundo real … en cuanto esa programación funcional permita trabajar con registros, direcciones de memoria, … podremos empezar a usarlo en el desarrollo de sistemas operativos.

  19. iabal said

    Decir que los bucles de C son parecidos a los del ensamblador me parece exagerado, sino los de Java (hasta la 1.4 que en la 1.5 entraron los foreach) también lo serían, ¿no?

    Veamos, puedes echarle un ojo a esto http://haskell.org/ghc/docs/latest/html/libraries/base/Foreign.html para ver como puedes manejar punteros y demás en Haskell, aunque no es el objetivo del lenguaje ni debería serlo.

    De todas formas, a diferencia de C, Haskell encapsula todo lo que pueda producir efectos colaterales en el mónada IO, evitando así,que por mucho que trabajes con direcciones de memoria o con E/S se produzcan efectos colaterales (siempre que no uses operaciones inseguras como unsafePerformIO).

    «Pero por el contrario permiten el control absoluto del hardware que haya por debajo. Por eso se usa en sistemas operativos. Y de sistemas operativos estamos hablando: el sistema operativo de la sonda.» A ver que googleo un poco… http://programatica.cs.pdx.edu/House/ Ahi tienes, un SO programado en Haskell, si quieres buscar más encontrarás SOs en muchos otros lenguajes.

    «Insisto: hay que manejar zonas de memoria cuando se hacen sistemas operativos. Me da igual que no te guste usarlas. Si no te gusta a lo mejor lo tuyo es hacer algoritmos matemáticos, o ventanitas, u otra cosa … pero no un sistema operativo.
    Las máquinas se manejan con instrucciones, registros, direcciones de memoria … y no se le puede decir “ponme el panel en este angulo”. Hay que escribir el ángulo en la posición de memoria tal. No hay más remedio.»

    Qué manía, el % de código (me refiero obviamente al codigo de los programas que tienes instalados) que existe en tu ordenador actualmente que realmente necesita un acceso a tan bajo nivel es infimo, sin embargo, el % de ese mismo código que está escrito en C es alto. ¿Qué sentido tiene?

    Yo no digo que haya que borrar a C del mapa, para cosas puntuales está bien usarlo por lo que tú dices de acceso a bajo nivel, pero me parece una estupidez que todo un SO tenga que ser escrito en C cuando realmente no se necesita, y no se necesita no porque lo diga yo, sino porque lo dicen muchos proyectos que han hecho SOs con lenguajes de alto nivel.

    Estos SOs pueden que tengan una proporcion 1/100 en el número de lineas, comparado con otro SO hecho en C, ¿cual es más fácil de mantener? ¿cual se tardó menos en programar? ¿cual es más robusto?

    «Si tu lenguaje de programación habitual es C, jamás se te ocurre cambiar un == por un = porque sabes perfectamente que hace cada cosa.»

    Perdona, creía que eras un humano y te equivocabas, ya veo que no es así. Porque si fueras un humano y te equivocases, esa equivocación en C te podría costar cara, mientras que en haskell tendrías un fallo en tiempo de compilación. A lo mejor crees que los programadores haskell no sabemos perfectamente que hace cada cosa.

    «Perfectamente consciente. Por eso se hacen distintos lenguajes de programación adaptados a cada necesidad.»

    Pues entonces no sé por qué no se usan.

    «El error está en querer usar el mismo para todas las cosas. php está para programación web, perl para administración de sistemas, c para desarrollo a bajo nivel, java y mono para desarrollo a alto nivel multiplataforma de casi todo … si te sobran recursos, python y ruby para desarrollo a alto nivel y administración de sistemas … programación funcional ¿para hacer un sistema operativo? Creo que no es su ámbito. La programación funcional es perfecta para otros ámbitos pero no en este.»

    A ver, ¿hablamos de lenguajes o de paradigmas de programación? El paradigma funcional sirve perfectamente para hacer todo lo que tu quieras, supongo que no tendré que volverte a pegar la url del proyecto House.

    Luego el tema de recursos está muy bien, C consume menos que haskell, pero luego resulta que los programas cientificos ultimamente se hacen en matlab.

  20. iabal said

    Me faltaba esto

    «“Cennc: Por eso el único camino hacia la perfección es la Verificación Formal + lenguajes funcionales ;)”
    No dudo que eso sea cierto en el mundo de las ideas de Platón, pero en el mundo real … en cuanto esa programación funcional permita trabajar con registros, direcciones de memoria, … podremos empezar a usarlo en el desarrollo de sistemas operativos.»

    Ya veo que tú normalmente usas los registros para todo… creo que si veo el código de cualquier SO, vamos, DUDO, que se usen los registros con mucha frecuencia.
    Aún así no sé que a viene eso de Platón y el mundo real, cuando te haga una casa un arquitecto dile que no haga calculos de estructuras, que coja un martillo y golpee un poco a ver si cae y ya, que total en el mundo real eso de hacer calculos es una estupidez para teóricos locos 😉

  21. Franz said

    Me imagino que alguien habrá perdido su trabajo por esto

Sorry, the comment form is closed at this time.