Comunicación IPC entre Node y .NET Core de plataforma cruzada utilizando descriptores de archivos / tuberías
Tengo una aplicación de terceros en Node que utiliza tuberías entre su proceso hijo y el proceso padre para la comunicación. Utiliza los descriptores de archivo subprocess.stdio[3]
y subprocess.stdio[4]
, en lugar de la entrada y salida estándar. Documentación relevante: https://nodejs.org/api/child_process.html#subprocessstdio
Creé una aplicación de .NET Core que se lanzó como el proceso hijo de la aplicación Node. La comunicación funciona bien en Windows. Se basa en el siguiente código de respuesta de SO: SO answer:
internal class Comm : IDisposable
{
[DllImport("MSVCRT.DLL", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr _get_osfhandle(int fd);
public readonly Stream Stream;
public Comm(int fd)
{
var handle = _get_osfhandle(fd);
if (handle == IntPtr.Zero || handle == (IntPtr)(-1) || handle == (IntPtr)(-2))
{
throw new ApplicationException("handle inválido");
}
var fileHandle = new SafeFileHandle(handle, true);
Stream = new FileStream(fileHandle, FileAccess.ReadWrite);
}
public void Dispose()
{
Stream.Dispose();
}
}
Dado que este código se basa en _get_osfhandle
de MSVCRT.DLL, ¿cómo puedo hacer que esta clase sea multiplataforma para que funcione en Windows, Linux y macOS? ¿Qué función debería importar en lugar de _get_osfhandle
?
davy.ai
Para que esta clase sea compatible con varias plataformas, la función
_get_osfhandle
de la bibliotecaMSVCRT.DLL
debe ser reemplazada por funciones específicas de cada plataforma.En Linux, se puede utilizar la función
dup
para duplicar un descriptor de archivo, seguida de la funciónfcntl
para recuperar las banderas del descriptor de archivo y establecer la banderaFD_CLOEXEC
. El descriptor de archivo resultante se puede utilizar para crear unFileStream
.En macOS, se puede utilizar la función
fcntl
con el comandoF_DUPFD_CLOEXEC
para duplicar un descriptor de archivo con la banderaFD_CLOEXEC
establecida, seguida de la creación de unFileStream
con el descriptor de archivo resultante.Aquí tienes una implementación de ejemplo que debería funcionar en Windows, Linux y macOS: