I know that shutdown -a will abort a Windows shutdown, but I need to know if there is anything any where I can check for to see if a shutdown is in progress.
Ideally, I'd like a small program like this:
import os
while True:
shuttingDown = <shutdown variable to check>
if shuttingDown:
os.system("shutdown.exe -a")
For preventing a Windows shutdown when it is happening, you can react to the WM_QUERYENDSESSION message (don't know if you can do that easily with Python's win32 API but it's simple in C). This might not prevent applications from closing because Windows sends WM_ENDSESSION to those that answer TRUE to the query message.
I guess you rather want to prevent a timed shutdown using "shutdown.exe". I'm sure that program uses InitiateSystemShutdown to show the shutdown dialog, but there are no resources on intercepting that call (at least I didn't find any or know of a Windows feature that allows such a thing).
Related
I have a Minecraft bedrock edition server running on our shared pc. I would like to interface with it via python. However, one problem I have is that my brothers sometimes restart our pc, or Windows updates. I need to know how to detect that shutdown event and send the shutdown command to the server before restart. I am using the subprocess library.
So, what you will need is the win32API and the function described here. You can use this function to add what's called a Control Handler Method that will run whenever the program is being shut down or terminated for any reason, including shutdown. You can find a list of the different codes that can be passed to the handler and their meanings here. Ideally, you should have a handler method that just shuts down the server, waits for it to finish shutting down, and then return.
I don't have any personal experience with the library, but it should be fairly straightforward.
EDIT: as noted by #ErykSun, you will need to create a hidden window in order to receive the events. To be quite honest I'm not sure how to create that hidden window. Some documentation suggests that running your application as a service may also work. I will look into this more if I get time.
Is there any way to prevent Windows from shutting down my system with Python. So I can't shutdown my system while my Python script is running?
yes there is.
from windows docs
Shutdown Notifications
Applications with a window and message queue
receive shutdown notifications through the WM_QUERYENDSESSION and
WM_ENDSESSION messages. These applications should return TRUE to
indicate that they can be terminated. Applications should not block
system shutdown unless it is absolutely necessary. Applications should
perform any required cleanup while processing WM_ENDSESSION.
Applications that have unsaved data could save the data to a temporary
location and restore it the next time the application starts. It is
recommended that applications save their data and state frequently;
for example, automatically save data between save operations initiated
by the user to reduce the amount of data to be saved at shutdown.
Console applications receive shutdown notifications in their handler
routines. To register a console handler, use the SetConsoleCtrlHandler
function. Service applications receive shutdown notifications in their
handler routines. To register a service control handler, use the
RegisterServiceCtrlHandlerEx function.
Blocking Shutdown
If an application must block a potential system shutdown, it can call the
ShutdownBlockReasonCreate function. The caller provides a reason
string that will be displayed to the user. The reason string should be
short and clear, providing the user with the information necessary to
decide whether to continue shutting down the system.
so you have to intercept the WM_QUERYENDSESSION message and return False .
and doing some web search i found a discussion about that how to intercept the WM_QUERYENDSESSION in python :
if you've built an app with a message loop, you can receive the
WM_QUERYENDSESSION message. If you want to have a GUI, most GUI
libraries will probably wrap this up in their own way. If you don't
need a GUI, your simplest solution is probably to use PyWin32.
Somewhere in the docs there's a tutorial on creating a hidden window
and writing a simple message loop. Just do that on the main thread,
and do your real work on a background thread, and signal your
background thread when a WM_QUERYENDSESSION message comes in.
Or, much more simply, just use SetConsoleCtrlHandler (again through
PyWin32). This can also catch ^C, ^BREAK, and the user closing your
console, as well as the logoff and shutdown messages that
WM_QUERYENDSESSION catches. More importantly, it doesn't require a
message loop, so if you don't have any other need for one, it's a lot
simpler.
i can't help with code snippet as i don't have access to windows pc and i don't want to share code without testing, but i hope i pointed you to what you should look for.
Reading through posts of similar questions I strongly suspect there is no way to do what I'm trying to do but figured I'd ask. I have a program using python3 that is designed to run headless, receiving commands from remote users that have logged in. One of the commands of course is a shutdown so that the program can be ended cleanly. This section is working correctly.
However while working on this I realized an option to be able to enter commands directly, without a remote connection, would be useful in the event something unusual happened to prevent remote access. I added a local_control function that runs in it's own thread so that it doesn't interfere with the main loop. This works great for all commands except for the shutdown command.
I have a variable that both loops monitor so that they can end when the shutdown command is sent. Sending the shutdown command from within local_control works fine because the loop ends before getting back to input(). however when sending the shutdown command remotely the program doesn't end until someone presses the enter key locally because that loop remains stuck at input(). As soon as enter is pressed the program continues, successfully breaks the loop and continues with the shutdown as normal. Below is an example of my code.
import threading
self.runserver = True
def local_control(): #system to control server without remote access
while self.runserver:
raw_input = input()
if raw_input == "shutdown":
self.runserver = False
mythread = threading.Thread(target=local_control)
mythread.start()
while self.runserver:
some_input = get_remote_input() #getting command from remote user
if some_input == "shutdown":
self.runserver = False
sys.exit(0) #server is shutdown cleanly
Because the program runs primarily headless GUI options such as pygame aren't an option. Other solutions I've found online involve libraries that are not cross-platform such as msvcrt, termios, and curses. Although it's not as clean an option I'd settle for simply killing the thread to end it if I could however there is no way to do that as well. So is there a cross-platform, non-GUI option to have a non-blocking input? Or is there another way to break a blocked loop from another thread?
Your network-IO thread is blocking the processing of commands while waiting for remote commands, so it will only evaluate the state of runserver after get_remote_input() returns (and it's command is processed).
You will need three threads:
One which loops in local_control(), sending commands to the processing thread.
One which loops on get_remote_input(), also sending commands to the processing thread.
A processing thread (possibly the main thread).
A queue will probably be helpful here, since you need to avoid the race condition caused by unsynchronized access as currently present with regards to runserver.
Not a portable solution, but in *nix, you might be able send yourself an interrupt signal from the local_control function to break the blocking input(). You'll need the pthread ID (pthread_self and save it somewhere readable from local_control) for the network control thread so you can call pthread_kill.
I have a python script that constantly runs (it has an infinite loop), but I want it to be able to still accept input while running. It will run in the background and then at any time I want to be able to type
scriptname stop
and stop it (or something like that). That way it can call a shutdown method to save information and quit.
Currently it runs in the foreground in the terminal, and can't be stopped by a keyboard interrupt, so the only way to kill it is to close the terminal or kill python.
How can I do something like this?
Use supervisord. It exists to manage processes, and provides a command interface to start and stop them.
When supervisor kills a process, it sends SIGTERM (or any other signal you choose). So, to shutdown cleanly, you need to handle that signal.
See this question on how to handle SIGTERM: Python - Trap all signals
Processes can still listen on their own pipes for input, and send output that way.
If you are in Windows then You are at right point...
Just Rename your file: script.py to script.pyw and Use It Normally.
Your Script will run in background.
To close that script:
Go to Task Manager , click on Process Tab , look out for python , End Task.
If You need more information I am Ready to Provide to you...
I am Not Sure About Linux or Ubuntu.
Thanks.
hello to you all :)
i have a program that have a n number of threads(could be a lot) and they do a pretty extensive job. My problem is that sometimes some people turn off or reboot the server(the program runs all day in the company servers) i know that there is a way to make a handler for the linux signals i want to know what i should do to interact with all threads making them to use run a function and then stop working. There is a way to do that?
sorry the bad english :P
The best way of handling this is not requiring any shutdown actions at all.
For example, your signal handler for (e.g.) SIGTERM or SIGQUIT can just call _exit and quit the process with no clean-up.
Under Linux (with non-ancient threads) when one thread calls _exit (or exit if you really want) other threads get stopped too - whatever they were in the middle of doing.
This would be good as it implements a crash-only design.
Crash-only design for a server is based on the principle that the machine may crash at any point, so you need to be able to recover from such a failure anyway, so just make it the normal way of quitting. No extra code should be required as your server should be robust enough anyway.
About the only thing you can do is set a global variable from your signal handler, and have your threads check its value periodically.
As others have already mentioned, signal handlers can get messy (due to the restrictions, particularly in multi-threaded programs), so it's better to chose another option:
have a dedicated thread for handling signals via sigwaitinfo - the bad news, though, is that python doesn't appear to support that out of the box.
use the Linux-specific signalfd to handle signals (either in a separate thread or integrated into some event loop) - at least there is a python-signalfd module you can use.
As there is no need to install signal handlers here, there is no restriction on what you can do when you are notified of a signal and it should be easy to shut down the others threads in your program cleanly.