Compare commits

..

9 Commits

Author SHA1 Message Date
dgtlmoon
627fd368fb Return exit status 2022-08-02 09:06:52 +02:00
dgtlmoon
f2f8469891 WIP 2022-08-01 21:02:07 +02:00
dgtlmoon
27117b324d Add comment 2022-08-01 19:30:04 +02:00
dgtlmoon
3cc7b8e489 Nope ignore it :) 2022-08-01 19:25:45 +02:00
dgtlmoon
307ce59b38 Handle SIGSTOP for suspend mode also 2022-08-01 19:23:38 +02:00
dgtlmoon
d1bd5b442b whitespace cleanup 2022-08-01 19:18:13 +02:00
dgtlmoon
a3f492bf17 use multiprocessing to wrap flask and use SIGTERM to save DB 2022-08-01 19:13:57 +02:00
dgtlmoon
58b0166330 Merge branch 'master' into sig-handler 2022-08-01 16:48:10 +02:00
dgtlmoon
fd080e9e4b Handle SIGINT somewhat 2022-07-04 20:52:15 +02:00
6 changed files with 20 additions and 55 deletions

View File

@@ -10,7 +10,7 @@ import multiprocessing
import signal
import os
def sigchld_handler(_signo, _stack_frame):
def sigterm_handler(_signo, _stack_frame):
import sys
print('Shutdown: Got SIGCHLD')
# https://stackoverflow.com/questions/40453496/python-multiprocessing-capturing-signals-to-restart-child-processes-or-shut-do
@@ -23,9 +23,7 @@ def sigchld_handler(_signo, _stack_frame):
raise SystemExit
if __name__ == '__main__':
#signal.signal(signal.SIGCHLD, sigchld_handler)
signal.signal(signal.SIGCHLD, sigterm_handler)
# The only way I could find to get Flask to shutdown, is to wrap it and then rely on the subsystem issuing SIGTERM/SIGKILL
parse_process = multiprocessing.Process(target=changedetection.main)
parse_process.daemon = True

View File

@@ -44,7 +44,7 @@ from flask_wtf import CSRFProtect
from changedetectionio import html_tools
from changedetectionio.api import api_v1
__version__ = '0.39.17.2'
__version__ = '0.39.17.1'
datastore = None
@@ -634,10 +634,14 @@ def changedetection_app(config=None, datastore_o=None):
update_q.put((1, uuid))
# Diff page [edit] link should go back to diff page
if request.args.get("next") and request.args.get("next") == 'diff':
if request.args.get("next") and request.args.get("next") == 'diff' and not form.save_and_preview_button.data:
return redirect(url_for('diff_history_page', uuid=uuid))
return redirect(url_for('index'))
else:
if form.save_and_preview_button.data:
flash('You may need to reload this page to see the new content.')
return redirect(url_for('preview_page', uuid=uuid))
else:
return redirect(url_for('index'))
else:
if request.method == 'POST' and not form.validate():
@@ -703,14 +707,7 @@ def changedetection_app(config=None, datastore_o=None):
return redirect(url_for('settings_page'))
if form.validate():
# Don't set password to False when a password is set - should be only removed with the `removepassword` button
app_update = dict(deepcopy(form.data['application']))
# Never update password with '' or False (Added by wtforms when not in submission)
if 'password' in app_update and not app_update['password']:
del (app_update['password'])
datastore.data['settings']['application'].update(app_update)
datastore.data['settings']['application'].update(form.data['application'])
datastore.data['settings']['requests'].update(form.data['requests'])
if not os.getenv("SALTED_PASS", False) and len(form.application.form.password.encrypted_password):

View File

@@ -19,10 +19,11 @@ app = None
def sigterm_handler(_signo, _stack_frame):
global app
global datastore
# app.config.exit.set()
print('Shutdown: Got SIGTERM, DB saved to disk')
app.config.exit.set()
datastore.sync_to_json()
# raise SystemExit
print('Shutdown: Got SIGTERM, DB saved to disk')
raise SystemExit
def main():
global datastore
@@ -90,7 +91,6 @@ def main():
datastore = store.ChangeDetectionStore(datastore_path=app_config['datastore_path'], version_tag=__version__)
app = changedetection_app(app_config, datastore)
signal.signal(signal.SIGTERM, sigterm_handler)
# Go into cleanup mode

View File

@@ -350,7 +350,7 @@ class watchForm(commonSettingsForm):
webdriver_js_execute_code = TextAreaField('Execute JavaScript before change detection', render_kw={"rows": "5"}, validators=[validators.Optional()])
save_button = SubmitField('Save', render_kw={"class": "pure-button pure-button-primary"})
save_and_preview_button = SubmitField('Save & Preview', render_kw={"class": "pure-button pure-button-primary"})
proxy = RadioField('Proxy')
filter_failure_notification_send = BooleanField(
'Send a notification when the filter can no longer be found on the page', default=False)

View File

@@ -307,7 +307,9 @@ Unavailable") }}
<div id="actions">
<div class="pure-control-group">
{{ render_button(form.save_button) }}
{{ render_button(form.save_button) }} {{ render_button(form.save_and_preview_button) }}
<a href="{{url_for('form_delete', uuid=uuid)}}"
class="pure-button button-small button-error ">Delete</a>
<a href="{{url_for('clear_watch_history', uuid=uuid)}}"

View File

@@ -19,6 +19,7 @@ def test_check_access_control(app, client):
)
assert b"Password protection enabled." in res.data
assert b"LOG OUT" not in res.data
# Check we hit the login
res = c.get(url_for("index"), follow_redirects=True)
@@ -37,40 +38,7 @@ def test_check_access_control(app, client):
follow_redirects=True
)
# Yes we are correctly logged in
assert b"LOG OUT" in res.data
# 598 - Password should be set and not accidently removed
res = c.post(
url_for("settings_page"),
data={
"requests-time_between_check-minutes": 180,
'application-fetch_backend': "html_requests"},
follow_redirects=True
)
res = c.get(url_for("logout"),
follow_redirects=True)
res = c.get(url_for("settings_page"),
follow_redirects=True)
assert b"Login" in res.data
res = c.get(url_for("login"))
assert b"Login" in res.data
res = c.post(
url_for("login"),
data={"password": "foobar"},
follow_redirects=True
)
# Yes we are correctly logged in
assert b"LOG OUT" in res.data
res = c.get(url_for("settings_page"))
# Menu should be available now