MCGalaxy icon indicating copy to clipboard operation
MCGalaxy copied to clipboard

auto restart doesn't work properly on linux/osx

Open UnknownShadow200 opened this issue 7 years ago • 3 comments

particularly with screen attached

I don't really know why though

UnknownShadow200 avatar Mar 05 '17 05:03 UnknownShadow200

This is because you use fork+exec not just exec.

            if (restarting) Process.Start(RestartPath);
            Environment.Exit(0);

If mono did this "properly" the Process.Start would never return as the current process would have been replaced by the new one.

The only access to the system facility I can find is the native call Mono.Unix.Native.Syscall.execv, which worries me a little, as the usual problem with calling execv from C is that buffers don't get flushed because the original process image is effectively killed.

I would suggest that for Unix the CLI wrapper is altered to call Process.Start the first time it runs. It'd need to use an argument so it doesn't fork-bomb and a special return code (eg: 109) to trigger the outside process to restart the main one.

rdebath avatar Mar 13 '21 14:03 rdebath

Problem is that after Process.Start(RestartPath), console input starts having issues image

And then after Environment.Exit(0), starts constantly erroring image image

Switching to calling execvp seems to work okay though (although not sure if that causes other subtle issues)

    if (restarting) execvp("mono", new string[] { "mono", RestartPath });
}
[DllImport("libc", SetLastError = true)]
static extern int execvp(string path, string[] argv);

Although still need to check how GUI behaves both with Process.Start and with execvp

UnknownShadow200 avatar Mar 14 '21 03:03 UnknownShadow200

The "console issue" is two processes (threads) arguing over the console. Mono/ReadLine does some heavy Ansi stuff to the console including sending the CSI 6n sequence to find how big the window is. With two of them sending it at the same time and the replies to both being randomly shared it gets very confused. This implies that you have a thread reading the console in the parent process even when you're waiting for the child.

The error is a little obscured, but it's probably due to the shell changing the "owner" of the terminal to prevent the same sort of mess happening to it. Normally a background job will be suspended if it tries to read from the standard input, but Mono is not normal.

If you're not actively multi-threading I'm told that this is the simple synchronous start and wait for a process to populate Process.ExitCode value. It can make the process "Not responding", which is what we want.

Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo( "notepad.exe" );
process.StartInfo = startInfo;
process.Start();
process.WaitForExit();
process.Close();

OTOH ...

Most issues with exec come in two flavours both based in the problem of exit and "OnExit" not being called.

  • Unflushed buffers; if the library buffers output it may be lost for files (and databases) that are not manually closed.
  • Unclosed file descriptors; Network connections, files, pipes etc all use file descriptors, most of them stay open over an exec.

Occasionally, you also get things like using setuid to change permissions, that state isn't completely reset either.

For GUI mode

Under Unix the GUI is a network connection to the X-server, this file descriptor should have the close-on-exec flag set. The new process will open a new connection based on the DISPLAY variable. However, unlike a CLI process, nothing normally waits for a GUI process to complete and the standard input is /dev/null already IF it's not started, in the foreground, from the shell.

This means the potential issues are the same as CLI, except that the GUI executable could preemptively background itself. Note though that "Docker" is an exception to this, if someone wants to use the GUI version in a Docker container (IMO a dumb idea) it must be possible to wait for it.

rdebath avatar Mar 14 '21 09:03 rdebath