New Version and Old Version same server

  • Hi Red,


    I run MR on a dedicated Windows server, I assume it will be possible to run both the unity server and the new version at the same time?


    Also, will the new version have any automatic restart functionally. I've had to manually restart MR ever morning for the last few... years... :dizzy: as for some reason or another the Task Scheduler wouldn't reliably start the server script after shutting the server down. Which is odd because I use TS at work for running scripts and that always works. *shrugs*

  • I run MR on a dedicated Windows server, I assume it will be possible to run both the unity server and the new version at the same time?

    Yes, you can run both servers simultaneously, as long as they're installed in different folders and use different ports ;)


    Also, will the new version have any automatic restart functionally

    Having a proper restart functionality is a bit problematic: You can't properly restart an application from within the application. In case of Java (the new version still needs a JVM for the plugin API), this introduces a few additional issues, since the JVM is very restrictive in this regard (once a VM, which was originally started from a certain process, is terminated, it's impossible to create a new one in the same process).


    It's always safer to have an external program or script which performs the restart. However, there are a few dirty and unsupported workarounds though to still restart an application. We did some experiments with that in the past (with the Java version), but it wasn't possible to reliably restart an application (resulting in undefined behaviour - sometimes it worked, sometimes it resulted in messed up "invisible" processes, depending on the OS). This may be different in the new version, we have to run a few tests before I can give any information about that.


    Windows offers a specific API to handle restarts, but that seems to be mainly intended to perform restarts after driver updates (or at least to release shared resources). I haven't looked into this API yet, but this would be obviously a very platform-specific solution (and even on Windows, this wouldn't be available on all versions).


    Maybe we could alternatively implement a "soft restart", without actually performing a fresh restart of the application (not an actual restart, instead this would be more like a "reset"). I'm not sure if this is sufficient - especially if something goes wrong, there may still be unreleased resources :thinking:


    In short, we will try to find a proper way to restart the server reliably, but unfortunately I can't give any guarantees :|

  • Well here is my backend RCON tool



    The 'master' Java application launched new 'slave' JVMs for the server using a ProcessBuilder, the StreamGobbler then effectively Tee's off the Output Stream and pushed the results to the GUI's ServerMonitor.


    I can then easily stop and start new slave JVMs from one master. I suppose if I spent more time on it I could automate the process. But with work and my new server plugin this has taken a backseat.


    Not to mention there is no gap buffer yet on my ServerMonitor so the master still needs restarting now and then as the StreamGobbler just appends the results



    I dunno, maybe something like this would solve the problem?

  • The limitations I've mentioned about the JVM don't apply if you launch a VM as a new process, but in case of the new version, we need to create a VM through JNI (we need the native interface for the communication between Java and C#/C++) - but creating a VM after destroying a previous one always results in a segmentation fault. It's not very clear whether this is intended behaviour (simply because recreation of a VM is unsupported) or a bug (there is a very old bug report [almost 20 years old] about this). Basically it's specific to JNI. There is a (rather small) discussion on stackoverflow about that: https://stackoverflow.com/ques…e-jvm-after-destroying-it


    But this isn't necessarily a major issue. Basically the main game faces the same issue (when returning to the main menu, which unloads the plugin API), so we make sure to have proper cleanup routines and we just reuse the old VM when loading another world (or joining another server). We could implement the same for the server itself (basically everything that's necessary for this is already in place [i.e. clean up network connections and release resources]), but I'm not sure if this is sufficient - if something goes wrong, this wouldn't work. Especially if any issues are related to the process (locks or issues with any connections), this wouldn't help at all (because it's still the same process).


    Starting a separate process from within the application doesn't work either - at least it's not reliable. Basically the process API always run new processes as child processes, and terminating the main process also terminates childs. It is possible to run a detached process (which is still alive after killing the original process), but this sometimes results in strange situations (like invisible processes, and sometimes they can't even be killed), especially after doing this multiple times. But as mentioned, we have to tinker with that a bit - it was quite problematic in Java, but it might work better in C++.


    Having a separate "launcher" which runs the game/server as child process is basically the proper way to do something like that (this is what our standalone is doing, but your RCON tool seems to be doing that as well?). In this case the "launcher" can always stop and restart the actual program at any time. But for our dedicated server, we don't have plans to introduce a separate launcher (since a launcher also introduces a few other issues - and it would also bloat the server).

  • I've not looked too much into this yet (it is Saturday night after all :) ), but couldn't you just start a JVM with the JNI that then creates a new JVM as needed?


    That would mitigate the segmentation fault? As the JVM started by the JNI would never be destroyed?


    Use the first JVM as a kind of bridge/ interface?

  • I've not looked too much into this yet (it is Saturday night after all :) ), but couldn't you just start a JVM with the JNI that then creates a new JVM as needed?

    That wouldn't help if it's still the same process. And in this case we need to find a way to communicate with the other JVM (that was started by the JVM), since all our native references and pointers wouldn't be valid anymore.


    That would mitigate the segmentation fault?

    It could be either a bug in the JDK, or this behaviour is simply not supported (which is more likely). In most cases there is almost never a situation you actually have to recreate a VM after destroying it ^^


    Use the first JVM as a kind of bridge/ interface?

    This would add a massive degree of complexity :wat: The API already got a lot complexer in the new version due to the communication between Java and the native side (via JNI). Right now the native part alone is more than 10k lines of code (without taking any Java code like the actual API into account), and some API stuff is still missing :dizzy:

    Passing data from Java to C#/C++ is quite easy, but receiving this data on the native side or passing data from native to Java (or vice versa) involves a lot of boilerplate code (especially if we're not only dealing with primitive datatypes, which is often the case in our API). If there was another bridge now this would make the API extremely bloated.


    ====================


    Nevertheless, the issue with the JVM is really just a minor issue compared to the other issues that evolve if an application restarts itself :nerd:

  • since all our native references and pointers wouldn't be valid anymore.

    Yea I guess that would cause an 'slight' problem!


    In most cases there is almost never a situation you actually have to recreate a VM after destroying it

    I guess that explains why a 20 yo 'bug' has never been fixed! ^^

    This would add a massive degree of complexity :wat: The API already got a lot complexer in the new version due to the communication between Java and the native side (via JNI). Right now the native part alone is more than 10k lines of code

    Without any ale in my system, thinking more clearly about it, yes that would mean writing code - for - every - single - getter - setter - constructor- and his aunt. And then every time one was added or changed. I do like creating work but this now sounds ridiculous! :D


    Best stick to Plan A! :saint:


    Have a Happy Easter red51 :thumbup:

  • Without any ale in my system, thinking more clearly about it, yes that would mean writing code - for - every - single - getter - setter - constructor- and his aunt. And then every time one was added or changed. I do like creating work but this now sounds ridiculous! :D

    Best stick to Plan A!

    Yeah that's true, that would be way too much additional work and redundant code (which, in return, would be fairly error prone) :drunk: Nevertheless, maybe we still find a way to offer a proper restart functionality. Maybe it's even sufficient to have something like that just for Windows: On Linux, it's fairly easy to set up a crontab via script, but on Windows, the TS seems to be a bit more problematic :thinking:


    Have a Happy Easter red51 :thumbup:

    Thanks, Happy Easter to you too :D

Participate now!

Don’t have an account yet? Create a new account now and be part of our community!