Hace 3 años | Por ccguy a lwn.net
Publicado hace 3 años por ccguy a lwn.net

A medida que el movimiento hacia los lenguajes seguros para la memoria, y Rust en particular, continúa creciendo, vale la pena mirar uno de los esfuerzos a mayor escala para portar el código C que ha existido durante décadas a Rust. El proyecto uutils tiene como objetivo reescribir todas las utilidades individuales incluidas en el proyecto GNU Coreutils en Rust. Creado originalmente por Jordi Boggiano en 2013, el proyecto tiene como objetivo proporcionar sustitutos para los programas Coreutils, añadiendo la protección de datos (..) de Rust.

Comentarios

ccguy

#7 Hombre, si una cosa tiene buena Rust (y tiene muchas) es que los errores más problemáticos de C son directamente imposibles (un programa erróneo no compila), y la inclusión de tests te la da directamente el toolchain.

Te recomiendo que le des una oportunidad.

pip

#8 pero tengo delante el changelog de Coreutils y la mayor parte de los errores los vas a tener igual en Rust, porque son errores de lógica, no errores de memoria o errores atribuibles al lenguaje C.

Ya te digo que el código está bien depurado por checkers, los errores de memoria saltan en los tests.

ccguy

#9 Eso crees tú Los bugs que haya en coreutils obviamente es porque aun no se han descubierto. De eso a que no haya....

pip

#13 no me creo que un código de 20 años con buena cobertura de tests y que se usa en millones de máquinas en producción y muchísimas variantes de sistema operativo tenga tantos errores de memoria.

Errores tiene, por supuesto, pero no veo justificada la re-escritura de varios miles de lineas de código estable porque sí.

Yo solo ver todos los problemas de compatibilidad que se han arreglado durante todos estos años, y que Rust no resuelve, ya me tiraría para atrás.

Además este proyecto de portar Coreutils a Rust no me parece que sea algo de la comunidad de Coreutils, más bien alguien que le ha dado por ahí.

ccguy

#14 Hombre, sólo con los errores en SSL creo que deberíamos tener la lección aprendida.

Lo único que puedo decirte es que pruebes Rust, pero que lo pruebes de verdad, porque una discusión sobre C y Rust sin haber probado Rust no tiene ningún sentido.

Cuando veas que el compilador te obliga a que todos los switch() sean exhaustivos (no puedes dejar un caso suelto), todos los errores gestionados, sea imposible dejar recursos sueltos, ni compartir memoria entre hilos sin utilizar las protecciones adecuadas (que Rust te da), etc... pues a lo mejor cambias de opinión.

Pero el argumento no puede ser que hay muchos tests (escritos a mano todos, claro) en coreutils.

ccguy

#16 Doy por supuesto que no conoces Rust por el camino que lleva el debate Pero si lo conoces, pues nada... no te quiero convencer de que te pongas a portar coreutils tú mismo.

Lo de merecer la pena es una cuestión personal. Para ti no, para los que lo están haciendo claramente sí, a mí me parece que está muy bien que lo hagan otros pero yo personalmente no lo haría porque soy un puto vago y sólo hago cosas si no las hace otro

Ya veremos con el tiempo si ha valido la pena. Dependerá de los resultados y si se aparece alguna cagada atómica en coreutils próximamente.

pip

#17 lo que te va a decir el tiempo, suponiendo que este señor o señores acaben el proyecto (no sé cuantos son y hablamos de 20 años de desarrollo de Coreutils), es que va a ser muy, muy dificil que una distribución meta el nuevo Coreutils sustituyendo el antiguo así sin más. La probabilidad de que rompas más cosas de las que arregles es altísima... yo desde luego no tendría narices a hacerlo, a ver como testeas eso.

Pero vaya, tampoco me voy a reiterar en mi opinión, ya está dicha pues nada, dicha queda.

D

#17 #19 ¡Iros a un hotel una dev conference!

D

#16
Si fuera a comenzar un proyecto nuevo escogería C++2x.
C/C++ MISRA.
Perfil C++ lifetimes.
Valgrind.
Cppcheck.
OpenMP.
OpenACC.
CUDA.
OpenCL.
HIP.
...

D

#23 Casi todo eso existe para C y mejor que la pesadilla de C++.

http://phroxy.z3bra.org/bitreich.org:70/0/con/2020/rec/energy-efficient-programming.md

Pura elegancia.

D

#27 lol

coderspirit

#16 Aun con lo que dices, sigue habiendo motivos muy sólidos (aunque lo son a largo plazo) para saltar a Rust en algún momento.

Empiezo por los argumentos débiles:
- Los changelogs nunca son exhaustivos, y más cuando hablamos de bugs críticos de seguridad.
- Que haya pocos errores de memoria no significa que no los haya.
- El mismo argumento que usaste sobre la simplicidad y poca criticidad de los programas (ls, rm, cat...) se puede aplicar a lo fácil que es evitar los errores lógicos que mencionas (además de que precisamente disponemos de código en el que basarnos para poder evitar los errores del pasado).

Yendo más en serio (y sí, estoy pensando a muy largo plazo):
- Los programas escritos en Rust pueden ser verificados formalmente con mucha mayor facilidad. Esto es importante por muchos motivos, pero dejemos-lo en que tiene implicaciones potenciales en seguridad, definiciones y verificaciones de estándares.
- Uno de los "problemas" actuales de Rust (vs C) es que no tiene definida una ABI estable (por motivos similares a los de C++), pero es improbable que eso continúe así para siempre (dada la vocación de lenguaje de sistemas que tiene Rust, y la de su comunidad de "reescribirlo todo"). Una vez se tenga una ABI estable, eso abre las puertas a que los kernels de sistemas operativos puedan exponer syscalls de forma más segura via algo rollo "librust" (en contraposición a "libc"), y en este punto tiene mucho sentido tener utilidades básicas de sistema capaces de sacar ventaja de esas nuevas interfaces más seguras.
- "Bootstrapping" a lo grande: Como todo lenguaje compilado que se precie, Rust ha pasado por una fase de bootstrapping, y hoy en día su compilador también está escrito en Rust. Pero aquí se acaba la historia, todo el proceso de construcción del binario sigue dependiendo de decenas de herramientas escritas en C y C++, empezando por... coreutils (aunque sin olvidarnos del elefante en la cocina, LLVM). Hacer bootstrapping a lo grande no es solo un ejercicio académico, tiene sentido si pretendemos aplicar técnicas de verificación formal sobre el compilador de Rust de forma más exhaustiva, que a su vez pueden ser necesarias (o ayudar mucho como mínimo) para poder generar binarios "certificados" que puedan usarse en entornos donde la seguridad (y los estándares) sean de importancia crítica. Por poner un caso relacionado, tenemos el proyecto "Ferrocene", iniciado por Ferrous Systems en Berlin, que pretende formalizar Rust lo suficiente como para ser aceptable en industrias como aviónica, aeroespacial y nuclear.

pip

#32 hombre los changelog no son perfectos pero no vamos a hacer ahora un análisis a fondo del historial de Coreutils commit por commit. Nos sirve como algo objetivo para ver claramente algunas cosas:

- Que el código es muy estable y tiene pocos cambios cada año.
- Que la inmensa mayoría de los fixes son de lógica y no son atribuibles al lenguaje C.
- Que los errores de memoria no serán tantos cuando está siendo todo sistemáticamente analizado por valgrind y hay fixes arreglando unos pocos bytes de leak.

coderspirit

#41 Pero no me he quedado en ese punto , y yo mismo lo he calificado como argumento débil.

pip

#42 era por no hacerte un commit con tantos temas a la vez

El mayor problema que tengo yo de Rust respecto a C es que somos un equipo con varias décadas, literal, de experiencia en C, y cientos de miles de código legacy C.
Eso hace también hay que valorarlo, porque tener a un señor que lleva 35 años programando en C pero está aprendiendo Rust, te introduce toda una serie de distorsiones donde ya no está tan claro que Rust sea tanta ventaja.

Aún así, llevamos por lo menos tres años considerando que un proyecto nuevo que se tuviese que hacer en C, podríamos hacerlo en Rust. Aún no se ha dado ese paso.

Y digo C queriendo decir C, no C++. Porque en C++ vs Rust hay muchas otras cosas que considerar, yo no considero a Rust un remplazo válido de C++, sino un remplazo válido de C en muchas ocasiones aunque no en todas.

coderspirit

#45 No continuo por "replicar", sino por continuar la conversación.

Veo normal que ciertos grupos y empresas se lo tomen con más calma, pero veo diferencias importantes entre que un colectivo específico cambie de herramientas, y entre que un nuevo proyecto (aunque imite a un antiguo proyecto) use esas nuevas herramientas.

Por otro lado, mucha de esa experiencia con C, en realidad tiene más que ver con conceptos abstractos que con el lenguaje en sí, y otra parte de esa experiencia se torna obsoleta cuando aparecen soluciones mejores o más sencillas.

En cuanto a lo de reemplazar C y no C++, de momento coincido contigo (aunque Rust no tenga ABI estable, puede usar la ABI de C)... pero sospecho que puede llegar a competir incluso con C++ en menos de una década.

pip

#46 pero C++ no está quieto, está en constante desarrollo. Cuando se creó Rust estábamos con C++98, y Rust tiene claras ventajas respecto a C++98. Sin embargo esas ventajas se reducen mucho cuando hablamos de C++17 o C++20, entendiendo que se programa bien C++ con técnicas modernas (si lo programas a la manera de C++98 no hacemos nada, lógicamente).
Pero de todas formas C++ tiene una serie de cosas que Rust no tiene y no quiere tener, por lo que para mí son lenguajes con paradigmas distintos y no tiene sentido compararlos, solo se puede comparar bien con C.
(Por ejemplo, ante la queja "Rust no tiene excepciones ni quere tenerlas", la respuesta no puede ser una disertación de por qué las excepciones son malas. En C++ tenemos excepciones o no, y tenemos soporte en el lenguaje para programar sin excepciones. Por tanto, si se ha decidido en un proyecto C++ que se van a usar excepciones, pudiendo no usarlas, la respuesta no puede ser que las excepciones son malas. Ya conocemos todos los pros y contras de las excepciones en la decisión, y en C++ podemos decidir, en Rust, no).

En el relato de la experiencia en el lenguaje C que tenemos te descuento ya la experiencia abstracta. DIgamos por resumir que el C tiene muchas cosas malas, pero las conocemos todas, y eso es una cosa buena.
Sin embargo no hay nadie en la empresa que conozca Rust ni de lejos al nivel de C como para asegurar que conoce todas las cosas malas de Rust.

D

#13 Las Coreutils se llevan usando en Unixes que valian mas que un Ferrari desde los 80.
Y estas tenian mejor fiabilidad que dichas utilidades Unix desde los 90.

https://minds.wisconsin.edu/bitstream/handle/1793/59964/TR1268.pdf

#14 Más de 30 anyos.

D

#8 >(un programa erróneo no compila),

-Wall -Werror -Wpedantic

ccguy

#25 Eso te corrige errores sintácticos y de tipo, por ejemplo. Pero no te valida por ejemplo que si estás haciendo un switch sobre un enum todos los valores posibles estén completados.

coderspirit

#25 Ni C ni C++ no se acercan ni de lejos, y ni con todas las herramientas de análisis estático que le eches encima, al tipo de verificaciones que ofrece Rust.

Hay muchos programas erróneos en C y C++ que compilan, aun con todas esas opciones, y aun después de haber pasado por herramientas como cppcheck. Y sí, en Rust podríamos decir "lo mismo"... salvo que el número de programas erróneos que serían compilados es muchísimo menor; eliminando clases enteras de problemas.

D

#33 >Hay muchos programas erróneos en C y C++ que compilan, aun con todas esas opciones, y aun después de haber pasado por herramientas como cppcheck

He. Coge un juego libre hecho en C++, activa -Wextra y sigue soñando.

O qué narices, cualquier emulador en C++ como los de Retroarch, o Dolphin.

coderspirit

#51 Eso es irrelevante, que ese código tenga errores fáciles de capturar no significa que después de corregir los fallos indicados no quedaran muchos otros que Rust sí detectaría.

Veo que o bien no lo entiendes o simplemente no lo quieres aceptar, pero los cambios que introduce Rust van mucho más allá de lo que permite cualquier compilador actual de C o C++. rustc es muchísimo más estricto que gcc, g++ o clang, y sus comprobaciones forman parte del lenguaje en sí, no son flags del compilador que uno pueda activar o desactivar a placer.

D

#52 Se lo que quieres decir. Pero -Wall -Werror es bastante draconiano.

D

#7
Para que Rust sea «seguro» tienes que especificar correctamente los ámbitos de las variables.
https://doc.rust-lang.org/rust-by-example/scope/lifetime/explicit.html

Algo que en C++ no hará falta:
https://pspdfkit.com/blog/2020/the-cpp-lifetime-profile/

ccguy

#21 cualquiera que haya estado en un banco sabe que es un milagro que funcionen las cosas

pip

A mí me van a perdonar, pero con todo el respeto a Rust, re-escribir algo que ya está escrito y bien probado en C me parece una tarea ociosa. Es más probable que se metan bugs nuevos a que se arreglen los que pueda tener el código actual.

Hay muchas herramientas para depurar el código en C en todo tipo de errores, que si bien son tediosas y requieren de arcanos sortilegios, el caso es que el código ya está hecho y en producción desde hace muchos años.

Que en fin, cada uno en su tiempo libre hace lo que quiere, faltaría más.

frg

#1 Lo mismo debieron pensar la gente de Mozilla cuando reescribieron su motor en Rush, una tarea ociosa, para generar nuevos bugs, y sin ningún beneficio, ...

pip

#2 no conozco los pormenores pero seguro que había gente opinando como yo. Tampoco tengo ninguna opinión concreta sobre Mozilla, no conozco los pormenores, si no sobre Coreutils, que sí lo conozco.

D

#2
Rust no es ninguna bala de plata. Ni tampoco es seguro.
Reinventar la rueda porque no sabemos hacer tests ni utilizar análisis estático ni dinámico.

D

#2 No compares algo tan complejo y en constante evolución como un motor HTML, con miniherramientas de línea de comandos que prácticamente no se tocan en años porque todo lo que tienen que hacer ya lo hacen, y estás requeteprobadas.

frg

#38 Igual es comparar ciervos con cucarachas, pero estas últimas están en todas partes, por lo que tenerlas saneadas no es descabellado.

ccguy

#1 Bueno, Rust garantiza corrección e impide muchos problemas. Librerías con C que están en todas partes y de las que al cabo de mucho años aparecen bugs salvajes hay unas cuantas.

La mayoría de herramientas de sistema de nueva generación se están escribiendo en Rust, por cierto, y muchas reemplazan a sus predecesores en C. baz, fd, rg, etc, para mí mucho mejores, aunque no son necesariamente compatibles y no se pueden usar sin más en scripts. Así que reescribir las originales tiene cierto sentido.

D

#5 Mejores? Bat es una mierda. Cat es para conCATenar archivos, puntos.

Lo demas son modas para hipsters que no entienden Unix.

ccguy

#24 Lo que tú digas

D

#29 Lo que yo digo no, la pura realidad. La gente que usa mal cat de primeras ya es la que no ha entendido Unix para nada.

Idomeneo

#1 una tarea ociosa

Cuando surgió Debian GNU/kFreeBSD había gente que preguntaba por qué se hacía y había una razón que sobresalía sobre todas las demás:

Because we can

Detalles aquí: https://lwn.net/Articles/329556/

D

#10 no es lo mismo: una cosa es querer hacer algo nuevo, diferente o con una filosofía distinta y otra es coger algo y rehacerlo en otro lenguaje.

Dicho de otra manera:
- me gusta Debian pero me molesta X e Y, así que me hago mi propia distribución cambiando X e Y por casinos y furcias (esto es un enfoque que te puede gustar más o menos, pero tiene una finalidad)
- oye, me voy a reescribir X en Rust (a priori no aporta nada y puedes añadir bugs nuevos)

D

#1 Esto me recuerda al código bancario o al de la gestión de los aviones. Es código pulido durante lustros, fiable, y pasar a otro lenguaje/plataforma da/daba escalofríos, pero me temo que llega un momento en que debe hacerse.

coderspirit

#21 El código de los bancos no es precisamente lo que yo diría "pulido", y de hecho suele contener cientos o miles de bugs latentes, incluso después de tantos años (en parte por el secretismo que aplican), sus estándares no se parecen en nada a los de la industria de la aviación.

ed25519

#1 Yo pienso que si algo funciona y esta bien, en el lenguaje que sea, cambiarlo por cambiarlo no tiene mucho sentido, pero vamos ahora que rust es un lenguaje en alza reinventar la rueda es algo que se pone de moda.

pip

#48 como ejercicio académico puede estar bien, en la práctica profesional muy mal tiene que estar un código que ya está en producción para escribirlo desde cero, aunque sea un código en C89, si está hecho y funcionando pues ahí está.
Si encima es un código estable sin bugs conocidos, el argumento de escribirlo de cero porque "seguro que tiene bugs que no conoces" no tiene ningún sentido.

ed25519

#49 Eso pienso yo, ademas saber cual es el comportamiento correcto puede ser una pesadilla la verdad

D

#43 No te lo discuto, pero desde hace unos años hay un movimiento muy fuerte contra la GPL en particular y las licencias víricas en general. Mucha gente opina (y yo estoy entre ellos) que toda la polémica con Stallman se convirtió en lo que se convirtió precisamente porque el objetivo es acabar con ellas (hoy por hoy, el único garante de que la GPL será siempre vírica es Stallman, realmente; sin él, es muy fácil que los proponentes de licencias no víricas, auspiciados por las grandes empresas, consigan meterse en la dirección de la FSF, reemplazando a todos los pro-viral, y sacar una GPLv4 que no lo sea... de pronto, todo software lanzado "bajo licencia GPLv2 o posterior" estaría disponible bajo una licencia no-viral).

D

Le he dado una lectura y he encontrado esto: "An important aspect of the uutils project to be aware of is its licensing. All of the utilities in the project are licensed under the permissive MIT License, instead of the GPLv3 license of GNU Coreutils."

Yo me huelo que la cosa va más por aquí que por el mero hecho de cambiar de lenguaje: desde hace tiempo hay un "movimiento en contra de las licencias víricas".

pip

#40 bueno eso es otro debate muy antiguo. Yo funciono respecto a eso de una manera egoísta: cuando estoy haciendo software propietario, agradezco poder meter una librería con licencia tipo MIT, claro que sí, es un chollo. Me parece genial.
Pero cuando tengo que contribuir yo a un código, estoy mucho más cómodo contribuyendo a código GPL, precisamente porque no me mola que venga un espabilado que podría ser yo mismo en otro contexto y use el código por la cara.

Como hago software libre y software propietario, soy como doctor Jekyll y mr. Hyde dependiendo del proyecto.

coderspirit

No, incorrecto. Rust es seguro por defecto, las lifetimes sólo se tienen que especificar en algunas situaciones muy concretas (pero no es requisito para que sea seguro). En cambio, C++ necesita herramientas externas para eso mismo, y sigue sin tener cosas como macros higiénicas, bloques match exhaustivos con desestructuración de variables, traits (mucho más limpios que los "concepts"...)...

coderspirit

#34 Esto iba para 11, pero parece que no me deja referenciar, interesante.

coderspirit

Respondí en #34 , pero parece que las referencias a este comentario no quedaron... ando bloqueado? no recuerdo haber dicho nada que pudiera ofender, pero vaya, sorpresas te da la vida.

D

Reinventar la rueda porque no sabemos hacer tests ni utilizar análisis estático ni dinámico.