Hi, Having had the APM bios fixed in the 0.7 Qemu release, which allows Windows 2000 to correctly signal Qemu when it wants to shutdown the VM, I've updated my '-on-quit' patch - which prevented the VM from being crudely shut down by accidentally pressing Ctrl-C or closing the VM window - to remove the nasty i386-specific "halt-instruction-detection" code and provide what I hope you will agree is a cleaner replacement. The new patch instead relies on APM/SDL/Cocoa/Cuda each specifying whether the shutdown request originated from the hardware or from the user. In the case of user request, Qemu's behaviour will depend on the command line option specified: 1. '-on-quit ignore' means ignore the Ctrl-C; 2. '-on-quit suspend' means suspend the VM. In the case of a hardware shutdown, the VM will shut down normally (but if '-on-quit suspend' was selected it will delete the named suspend file first). The patch features extra options '-on-quit ask' and '-on-quit <filepath>' which both cause Qemu to run a script to ask the user whether they want to resume, suspend or power off the VM. For non-WIN32 platforms, this is easily implemented it using a script that the xmessage command i.e.: #!/bin/sh exec /usr/bin/X11/xmessage -center -timeout 10 -buttons 'Resume:0,Suspend:1,Power Off:2' 'Do you want to resume, suspend, or power off this virtual machine?' The '-on-quit ask' option assumes a default script filename "on_quit_ask", assumed to be in the CONFIG_QEMU_SHAREDIR directory (i.e. usually /usr/local/share/qemu). Example command (Linux) which should correctly buffer naive users from accidental VM shutdown and suspend file overwriting: it resumes from suspended.qemu file if it exists; asks user whether to resume, power off or suspend on CTRL-C or window close; suspend saves to the same file; power off deleted the suspend file. qemu -hda win2k.raw -m 64 -monitor null -loadvm suspended.qemu -on-quit ask Feedback welcome! Struan Struan Bartlett wrote:
|
diff -r -U3 qemu-snapshot-2005-05-06_23/cocoa.m qemu-snapshot-2005-05-06_23-on-quit-v0.2/cocoa.m --- qemu-snapshot-2005-05-06_23/cocoa.m Thu Apr 7 22:36:50 2005 +++ qemu-snapshot-2005-05-06_23-on-quit-v0.2/cocoa.m Sat May 7 15:41:23 2005 @@ -444,7 +444,7 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification { printf("Application will terminate\n"); - qemu_system_shutdown_request(); + qemu_system_shutdown_request(1); /* In order to avoid a crash */ exit(0); } diff -r -U3 qemu-snapshot-2005-05-06_23/hw/cuda.c qemu-snapshot-2005-05-06_23-on-quit-v0.2/hw/cuda.c --- qemu-snapshot-2005-05-06_23/hw/cuda.c Sat Apr 23 20:16:54 2005 +++ qemu-snapshot-2005-05-06_23-on-quit-v0.2/hw/cuda.c Sat May 7 15:41:06 2005 @@ -532,7 +532,7 @@ obuf[0] = CUDA_PACKET; obuf[1] = 0; cuda_send_packet_to_host(s, obuf, 2); - qemu_system_shutdown_request(); + qemu_system_shutdown_request(1); break; default: break; diff -r -U3 qemu-snapshot-2005-05-06_23/hw/pc.c qemu-snapshot-2005-05-06_23-on-quit-v0.2/hw/pc.c --- qemu-snapshot-2005-05-06_23/hw/pc.c Sat Jan 15 13:02:56 2005 +++ qemu-snapshot-2005-05-06_23-on-quit-v0.2/hw/pc.c Sat May 7 16:20:42 2005 @@ -297,7 +297,7 @@ shutdown_index++; if (shutdown_index == 8) { shutdown_index = 0; - qemu_system_shutdown_request(); + qemu_system_shutdown_request(-1); } } else { shutdown_index = 0; diff -r -U3 qemu-snapshot-2005-05-06_23/sdl.c qemu-snapshot-2005-05-06_23-on-quit-v0.2/sdl.c --- qemu-snapshot-2005-05-06_23/sdl.c Mon Jan 17 23:32:23 2005 +++ qemu-snapshot-2005-05-06_23-on-quit-v0.2/sdl.c Sat May 7 16:33:15 2005 @@ -414,7 +414,7 @@ sdl_process_key(&ev->key); break; case SDL_QUIT: - qemu_system_shutdown_request(); + qemu_system_shutdown_request(1); break; case SDL_MOUSEMOTION: if (gui_grab) { diff -r -U3 qemu-snapshot-2005-05-06_23/vl.c qemu-snapshot-2005-05-06_23-on-quit-v0.2/vl.c --- qemu-snapshot-2005-05-06_23/vl.c Sat Apr 30 18:10:35 2005 +++ qemu-snapshot-2005-05-06_23-on-quit-v0.2/vl.c Sat May 7 18:25:11 2005 @@ -144,6 +144,11 @@ #endif int graphic_depth = 15; int full_screen = 0; + +#define ON_QUIT_ASK_FILENAME "on_quit_ask" +int on_quit = 0; +const char * on_quit_filepath = NULL; + TextConsole *vga_console; CharDriverState *serial_hds[MAX_SERIAL_PORTS]; CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; @@ -2581,9 +2586,27 @@ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); } -void qemu_system_shutdown_request(void) +void qemu_system_shutdown_request(int s) { - shutdown_requested = 1; + + if (s == 1 && on_quit == 3) { // User power-off request and Popup message setting + int r,c; + + if( on_quit_filepath ) r = system(on_quit_filepath); + else { + char buf[1024]; + snprintf(buf, sizeof(buf), "%s/%s", CONFIG_QEMU_SHAREDIR, ON_QUIT_ASK_FILENAME); + r = system(buf); + } + c = WEXITSTATUS(r); + + if(c == 0) return; + if(c == 2) s = -1; // Simulate an APM power-off request + // else if r == -1, there was an error; if c == 1, then suspend; + // Either way, we suspend, for safety + } + + shutdown_requested = s; cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); } @@ -2701,8 +2724,11 @@ if (vm_running) { ret = cpu_exec(env); if (shutdown_requested) { - ret = EXCP_INTERRUPT; - break; + if (on_quit == 0 || on_quit == 2 || on_quit == 3 || (on_quit == 1 && shutdown_requested == -1)) { + ret = EXCP_INTERRUPT; + break; + } + shutdown_requested = 0; } if (reset_requested) { reset_requested = 0; @@ -2803,6 +2829,9 @@ "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n" " (default is CL-GD5446 PCI VGA)\n" #endif + "-on-quit [ignore|suspend|ask|<script filepath>]\n" + " select the behaviour when the emulator window is asked to quit\n" + " (default is none)\n" "-loadvm file start right away with a saved state (loadvm in monitor)\n" "\n" "During emulation, the following keys are useful:\n" @@ -2885,6 +2914,8 @@ QEMU_OPTION_pidfile, QEMU_OPTION_no_kqemu, QEMU_OPTION_win2k_hack, + QEMU_OPTION_on_quit, + }; typedef struct QEMUOption { @@ -2954,6 +2985,7 @@ { "full-screen", 0, QEMU_OPTION_full_screen }, { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, + { "on-quit", HAS_ARG, QEMU_OPTION_on_quit }, /* temporary options */ { "pci", 0, QEMU_OPTION_pci }, @@ -3415,6 +3447,18 @@ kqemu_allowed = 0; break; #endif + case QEMU_OPTION_on_quit: + if(!strncmp(optarg, "ignore",6)) { + on_quit = 1; + } + else if(!strncmp(optarg, "suspend",7)) { + on_quit = 2; + } + else { + on_quit = 3; + if(strcmp(optarg, "ask")) on_quit_filepath = optarg; + } + break; } } } @@ -3723,6 +3767,20 @@ } } main_loop(); + + if (on_quit == 2 || on_quit == 3) { + char *f = "suspended.qemu"; + if (shutdown_requested == -1) { // APM-request to shutdown + + fprintf(stderr, "VM is halted: removing suspend file %s\n",f); + unlink(f); + } + else { // User-request to shutdown + fprintf(stderr, "Autosaving VM to file %s\n",f); + qemu_savevm(f); + } + } + quit_timers(); return 0; } diff -r -U3 qemu-snapshot-2005-05-06_23/vl.h qemu-snapshot-2005-05-06_23-on-quit-v0.2/vl.h --- qemu-snapshot-2005-05-06_23/vl.h Sat Apr 30 18:10:35 2005 +++ qemu-snapshot-2005-05-06_23-on-quit-v0.2/vl.h Sat May 7 15:41:49 2005 @@ -109,7 +109,7 @@ void qemu_register_reset(QEMUResetHandler *func, void *opaque); void qemu_system_reset_request(void); -void qemu_system_shutdown_request(void); +void qemu_system_shutdown_request(int); void main_loop_wait(int timeout);
_______________________________________________ Qemu-devel mailing list Qemu-devel@nongnu.org http://lists.nongnu.org/mailman/listinfo/qemu-devel