With the bounty in place, my aim was to update the blog more often -- preferably when I had some sort of update. However, my time has been lacking the last few weeks, and I haven't made as much progress as I wanted. But the bounty has surely made me more motivated -- your donations are much appreciated. In order to get some well needed progress, I've earmarked two "mellandagar" (i.e. the days between christmas and new year) to fully focus on Jamiga. I'm hoping nothing will interfere with these plans.
Controlling the signal
So, why this blog entry? Well, its because I've actually made some progress! I've managed to sort out the signal handling. Now I cannot only run multi-threaded Java programs, I can also break them forcefully by pressing Ctrl-C. It might not seem like a big whoop, but it is really, really nice to be able to halt the Java process, and being able to do so in a stable manner. I have described the signaling previously, but I'll take it in more detail now.
JamVM is aimed to run on a pthread capable OS. I've managed to wrap all pthread functions needed (as in needed by JamVM, and specifically tied to JamVM -- it is not a general purpose pthread implementation). There are at least four threads needed for one single instance of JamVM:
- The main process
- Finalizer thread
- Reference handler
- Signal handler which should catch any signals, i.e. Ctrl-C and such
- ... plus any number of possible Java threads
The way it's intended, in a pthread environment, the signal handler catches all signals sent to the JamVM process. Upon receiving Ctrl-C the signal handler executes the Java class "System.exit()", and the exits the program by using the C function exit(). There is however a problem with this approach in the Amiga environment. A child process cannot run exit() to end the main process, so AmigaOS decides to only do a RemTask for any child processes calling exit(), which will leave all the other processes running. I managed to circumvent this exit()-calling by some signal sending back and forth; the signal handler actually signals the main process to shut down the virtual machine and the call exit().
In a real pthread environment, all the four threads are run inside one actual OS process, so the OS only sees one process and signals sent can be redirected to either thread. On AmigaOS the four threads are are actually four different processes, so anyone of them can be signaled independently (from like Ranger), and the main process is the most likely target. For instance, when running a Java console application and pressing Ctrl-C, the main process gets signaled, and not the Signal handler. However, this is not a big problem. I merely redirect the signal to the Signal handler, by setting up an exception handler (with SetExcept()) for each process that catches all signals and sends it to the Signal handler. The Signal handler calls Java method "System.exit()", and signals any running Java threads to stop what they're doing, and then signals the main process, which in turn signals any running JVM process (the Finalizer, Reference handler and Signal handler) to stop what they're doing. And then we're done.
When the signaling bits are fully done (I must re-factor and cleanup the mess its currently in), I will resurrect my networking stuff. I ended up in this signaling mess trying to end a network process that hung for some reason, and I was fed up with rebooting my Amiga just to release the TCP-ports. You can see a small screenshot above of my attempts (and partial success) with running two Java instances sending data from client to server. The reason I cannot break this using Ctrl-C is that the networking process eats the Ctrl-C. And I guess that's what I'll be doing on my two "mellandagar".
The selected top Shell process with the three child processes is the Java network client (you can see the command "jamvm.exe ServerClientExample", which runs the ServerClientExample class). The next Shell process with the three familiar child processes is the other JamVM instance, running the Java server. This also has two children, the Jamiga socket processes, which are the processes handling the networking, as I described about a year ago.