Add GC guards around open() because there are cases where it can block

Caught during a CI run on Linux. open() can block for example when used
with pipes. Also make sure to handle any errors that might need to be
thrown. Using strdup here is safe, because we already ensure that the
string is a safe C null terminated string.