Commit Graph
124 Commits
Author SHA1 Message Date
Adrian Torres ee29cb9147 [FIX] tests: make --test-file great again
Sort of but not really, this commit fixes a special case in which
launching a --test-file of a file with at least two SavepointCases would
create a postgresql deadlock and it would be impossible to terminate the
Odoo process without sending a SIGKILL or waiting for the lock to
timeout.

This was introduced at #39368 and happens because of the way that
unittests unwraps suites, to keep it short, when it unwraps the custom
OdooSuite class internally, it ends up with a vanilla TestSuite with
which to run the different test cases, and since #39368 depends on the
overrides added to OdooSuite to function, the class cleanups are not
triggered at the end of a test class (rollback, cache cleanups, env
reset, registry reset, etc.).

The fix is to manually unwrap the suite of tests to keep OdooSuite as
the suite with which to call the tests, which was already done for
--test-enable (although for different reasons, --test-tags?) which is
why --test-enable didn't have any problems.

This commit also fixes a typo I found on the backport, which meant
classCleanups were not being executed if the setUpClass failed, but it
had no effect on classCleanups during tearDownClass.

Task-ID 2160398
Depends on #43135

closes odoo/odoo#43296

X-original-commit: 7a5ded7d40afc29043d356b5dece0dbe1fbd5ab3
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
2020-01-14 16:26:50 +00:00
Xavier Morel 80896a0bf3 [FIX] core: chrome doesn't abide by --http-port anymore
An http-port provided on the command line (may also have been an issue
for config files, didn't check) would not be taken in account anymore,
because `odoo.tests.common` would be imported during the import of
`odoo` itself (when loading odoo.service.server), itself importing
`odoo.tools.config` leading to a default configuration being set up.

* remove `odoo.tests.common.PORT`, `config['http_port']` should be
  used always
* defer the import of odoo.tests.common by moving it inside
  load_test_file
* stop generating default configs

closes odoo/odoo#43283

X-original-commit: 45871f498ea4cf3ada719692e69cd413883ab442
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2020-01-14 13:15:04 +00:00
Fabien Meghazi 543a3ad204 [FIX] server: limit concurrent http threads
Before this commit nothing prevented high concurrency on a threaded http
server to consume too much resources, ending up failing requests either
because the OS is unable to spawn that many threads
(`RuntimeError: can't start new thread`), either because the Odoo db
connection pool is full (`PoolError: The Connection Pool Is Full`).

This commit adds the ODOO_MAX_HTTP_THREADS environment variable which
allows to limit the amount of concurrent socket connections accepted by
a threaded server, implicitly limiting the amount of concurrent threads
running for http requests handling.

Note that if a value has been provided to ODOO_MAX_HTTP_THREADS that cannot
be parsed as an integer, a value will be automatically set to half the
db connection pool size (which defaults to 64). This dynamic value is
chosen because while most requests will borrow only one cursor
concurrently, there are some exceptions where some controllers might
allocate two or more cursors.

closes odoo/odoo#42327

X-original-commit: d42a951369ee87b50e834f73cd2af5cf031d43f7
Signed-off-by: Christophe Simonis <chs@odoo.com>
2019-12-23 18:56:09 +00:00
Fabien Meghazi 6ddf7a50b5 [IMP] server: prevent threaded server to exceed memory limit due to malloc's arenas
glibc's malloc() uses arenas [1] in order to efficiently handle memory
allocation of multi-threaded applications. This allows better memory
allocation handling in case of multiple threads that would be using
malloc() concurrently [2].

Due to the python's GIL, this optimization have no effect on
multithreaded python programs. Unfortunately, a downside of creating one
arena per cpu core is the increase of virtual memory which Odoo is based
upon in order to limit the memory usage for threaded workers.

On 32bit systems the default size of an arena is 512K while on 64bit
systems it's 64M [3], hence a threaded worker will quickly reach it's
default memory soft limit upon concurrent requests. We therefore set the
maximum arenas allowed to 2 unless the MALLOC_ARENA_MAX env variable is
set.

This commit also brings the following changes:
- allow to disable the memory hard limit for all servers if the provided
  value is 0 (instead of crashing)
- increase the log level for threaded server in case of limits reached

Note: Setting MALLOC_ARENA_MAX=0 allow to explicitely set the default
      glibs's malloc() behaviour.

[1] https://sourceware.org/glibc/wiki/MallocInternals#Arenas_and_Heaps
[2] https://www.gnu.org/software/libc/manual/html_node/The-GNU-Allocator.html
[3] https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=00ce48c;hb=0a8262a#l862

closes odoo/odoo#42323

X-original-commit: 85fe2c6e60f7f1f6ea72cb55e85f85d420ce6616
Signed-off-by: Christophe Simonis <chs@odoo.com>
2019-12-23 18:03:35 +00:00
Denis Vermylen 4b1668abc3 [FIX] server.py: <threaded> avoid registry lock upon shutdown
A deadlock can occur between threads when concurrent requests
acquire the registry lock and conflicting database-level locks
in different orders. The database won't be able to detect and
break the deadlock because it involves an external, Python-level
lock. This situation is more likely to occur during module
installations [1].

If the server is started with the `limit_time_real` option,
it should be able to abort the deadlocked requests after the
timeout, and restart. However that could not work because
the recovery initiated by `reload()` is blocked at the end
of the `stop()` method, as it cannot acquire the registry
lock either, necessary for `Registry.delete_all()`.

Since that deletion step is in fact not necessary, it can
be skipped, avoiding the deadlock entirely.

Indeed there's no real reason anymore to delete the DB's
registry upon shutdown. This was introduced for 7.0 by
b5daffc115, in order to perform
other cleanups (including cron agent threads). These other
cleanups are not necessary anymore, and when the stop()
method of the ThreadedServer completes, the next step is
either a restart of the whole process (via execve() through
_reexec()), or a full process exit. Keeping the registry in
memory for a few cycles until this happens makes no difference.

When such a deadlock occurs, it's always possible to manually
kill the server with 2 `kill` commands, or 1 `kill -9`.

~~~~~~~~~~~~~~~~~~~~~~
[1] Reproduction info:

The following deadlock was observed in Odoo threaded server mode:

1. incoming request spawns a new thread A
   A starts a transaction and does a "SELECT ... FROM res_users ..."
   getting an ACCESS SHARE lock on the table
2. incoming request spawns a new thread B
   B is a request that calls `button_immediate_install`, that will
   install new modules and alter the res_users table.
3. B takes and holds the registry lock and executes "ALTER TABLE
   res_users ...", that waits to get the ACCESS EXCLUSIVE lock on the
   table until A's transaction releases the ACCESS SHARE lock.
4. A continues code execution and reaches a .sudo() call, it tries to
   create a new environment. The creation of the new environment
   requires to wait for the registry's lock to be release but it's held
   by B.

-> A waits for B's registry lock to be released
-> B waits for A's ACCESS SHARE lock to be released
-> Deadlock that can't be broken except by force-killing the server

closes odoo/odoo#40664

X-original-commit: 9e67525418b3b0a48a796044ef24b227946ceb8f
Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
2019-11-21 20:38:00 +00:00
Adrian Torres ec587297eb [IMP] tests: partially backport classCleanups from CPython 3.8
This commit partially backports bpo-24412, which allows the definition of
class cleanups (addClassCleanup) and module cleanups (omitted),
similar to instance cleanups (addCleanup).

This is useful for tests that override unittest's setUpClass and
could crash during its execution: If this happens, it is possible that a
bunch of crap is left in the database or even worse, the cursor becomes
completely fucked; Thanks to the addClassCleanup, we can undo the damage
done by the setUpClass.

Another benefit is that it is called unconditionally after tearDownClass
is called, so it can also be called as a replacement and/or safer
tearDownClass.
2019-11-06 14:07:04 +00:00
Xavier Morel 79313d8817 [FIX] core: SIGXCPU in worker processes
odoo/odoo#30688 (6ce2d6efb5) added an
indirection in prefork workers: Python-level signal handlers are
delayed until native calls have ended (e.g. accept() or
execute()). Running the actual work in a sub-thread allowed the main
thread to handle signals in all cases.

However there is apparently an issue with SIGXCPU on linux (possibly
other cases as well): SIGXCPU is delivered to the child thread (if
possible?) and Thread.join apparently stops it from redelivered to
the main thread (Thread.join is signal-interruptible since 3.2 but
possibly not Python-interruptible).

Blocking SIGXCPU on the child thread causes the OS to deliver on the
main thread and fixes the issue.

Also split set_limits so it sets the signal handler in the parent
thread but properly updates the soft limit in the child after each
request, as the goal is to put a hard limit on the CPU time per
request, not on the worker. 6ce2d6ef would set the limit once then
never update it, likely cycling workers more than desired.

While at it:

* block other signals with a handler set, they seem to work
  regardless on linux but other OS may have a different way of
  dispatching process-directed signals
* unset signals which are set by the prefork server but whose
  set behavior makes no sense in workers:

  - TERM and CHLD were already unset
  - HUP is used to restart the server, workers can just be killed
  - TTIN and TTOU configure the number of workers

closes odoo/odoo#39731

X-original-commit: 549bd199bad269e4e28efac933efac3f41495877
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2019-11-04 11:35:59 +00:00
Christophe Simonis d74b451805 [MERGE] forward port branch 13.0 up to f4105eb9c7 2019-10-09 02:08:17 +02:00
Christophe Simonis d67b2483e5 [MERGE] forward port branch saas-12.4 up to 9ed4872ea0
closes odoo/odoo#37372

Signed-off-by: Christophe Simonis <chs@odoo.com>
2019-09-24 17:45:37 +00:00
Denis Vermylen bd3e510edb [IMP] odoo: dump stacktrace of timed out threaded workers
So the logs contain some indication as to what was exceeding the limits.

closes odoo/odoo#37303

X-original-commit: 0a266f444a0abda026d09ad88024dca1c50c92b9
Signed-off-by: Denis Vermylen <Icallhimtest@users.noreply.github.com>
2019-09-23 14:16:04 +00:00
Denis Vermylen 4fb712f729 [FIX] service: do not call nonexistent function
omission in d26e253edd

kill -3 (SIGQUIT) is not processed like the other signals so it doesn't
go through this bit of code, but leaving the AttributeError lurking
there is not a good idea.

closes odoo/odoo#37221

X-original-commit: ac65ef0208a5ec814d263aeb44a98b47a5ee3947
Signed-off-by: Denis Vermylen <Icallhimtest@users.noreply.github.com>
2019-09-21 13:59:06 +00:00
Julien Castiaux 7c47eb1854 [IMP] module.py: deprecate openerp
[PEP-594] is deprecating the `imp` module, that module is used in
`module.py` in order to dynamically import addons using any of the
`odoo.addons` or `openerp.addons` import anchor.

We are deprecating `openerp` module/addons imports in v13 in order to
remove the support in v14 and greatly simplify how modules/addons are
loaded. If you are still using the old `import openerp` or `import
openerp.addons`, `import odoo` and `import odoo.addons` are drop-in
replacements.

The `odoo.modules.module.ad_paths` addon paths list has been deprecated
too. The list is now accessible on `odoo.addons.__path__` where they
are now directly loaded [2].

See also:

[PEP-594]: https://python.org/dev/peps/pep-0594/
[2]: https://packaging.python.org/guides/packaging-namespace-packages/

closes odoo/odoo#36597

Task: 2003936
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2019-09-16 09:31:38 +00:00
Julien Castiaux d47083e6d2 [IMP] module.py: deprecate openerp
[PEP-594] is deprecating the `imp` module, that module is used in
`module.py` in order to dynamically import addons using any of the
`odoo.addons` or `openerp.addons` import anchor.

We are deprecating `openerp` module/addons imports in v13 in order to
remove the support in v14 and greatly simplify how modules/addons are
loaded. If you are still using the old `import openerp` or `import
openerp.addons`, `import odoo` and `import odoo.addons` are drop-in
replacements.

The `odoo.modules.module.ad_paths` addon paths list has been deprecated
too. The list is now accessible on `odoo.addons.__path__` where they
are now directly loaded [2].

See also:

[PEP-594]: https://python.org/dev/peps/pep-0594/
[2]: https://packaging.python.org/guides/packaging-namespace-packages/

closes odoo/odoo#36597

Task: 2003936
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2019-09-20 05:58:16 +00:00
Julien Castiaux 4f03a5f136 [FIX] *: remove old deprecated modules/functions
PEP-594 is deprecating a bunch of modules. As part of the cleanup, we
are also dealing with long deprecated modules, functions and aliases.

* `assert_` -> `assertTrue`
* `assertEquals` -> `assertEqual`
* `assertNotEquals` -> `assertNotEqual`
* `assertAlmostEquals` -> `assertAlmostEqual`
* `assertRaisesRegexp` -> `assertRaisesRegex`
* `assertRegexpMatches` -> `assertRegex`
* `base64.encodestring` -> `base64.encodebytes`
* `base64.decodestring` -> `base64.decodebytes`
* `inspect.getargspec` -> `inspect.signature`
* `inspect.formatargspec` -> `inspect.signature`
* `logging.warn` -> `logging.warning`

closes odoo/odoo#36863

Task: 2003936
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
2019-09-17 11:36:42 +00:00
Xavier Morel ae8770e704 [FIX] core: gevent / longpolling logging
* fix the gevent worker "logging" everything to stderr and ignoring
the logging configuration: passing loggers to WSGIServer means it
uses those loggers instead of writing directly to stderr
* fix the gevent worker logging the wrong client address when behind a
reverse proxy: it would log the client_address, immitate the
behaviour of werkzeug which goes and gets whatever REMOTE_ADDR is
set on the environment, that way it gets whatever update were
performed by ProxyFix (if any)

Fixes #32914

closes odoo/odoo#36233

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2019-08-29 13:17:02 +00:00
Xavier-Do 735ee5487c [IMP] core: improve test logs
1. Make test logs clearer & remove redundancies

Instead of having an ERROR log right when the test fails then print
the useful / relevant information at the end of the test suite,
immediately print the traceback. Keep the final summary. Also avoids
having to wait for the entire test suite to end before a dev' can know
the failure details of a specific test.

Done by working at a lower level and replacing the custom
test stream mess by a custom Result class which prints and formats the
information we want. Replace TextTestRunner by a bare-bones custom
Runner object to tie it in.

2. Provide useful location information on test failure

Leverage the work above to log the test function's failure location:
previously logging would point to within TestStream which is not
useful.

Here, on failure the traceback is used to discover the caller info and
point to the test line which fails instead. similar to unittest's
_exc_info_to_string (https://github.com/python/cpython/blob/93e8aa62cfd0a61efed4a61a2ffc2283ae986ef2/Lib/unittest/result.py#L173).

3. Replace direct logging in browser_js by raising errors

Properly marks the test as in error, and the error traceback points to
the tour definition / launcher (python side) rather than common.py
and/or module.py.

Also removes unused dbname parameter that was added in
/278ed718e9805edf088642ba10d3b7c4e5716c31/openerp/modules/module.py#L361
for nor visible reason

closes odoo/odoo#34996

Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
2019-07-25 12:09:27 +00:00
Simon Lejeune 22221a2b57 [REF] server: better warnings when using --test-file
We add two warnings to make the --test-file argument more user friendly:
- one when the test file does not exist
example:
./odoo-bin -d master --test-file ./addonss/stock/tests/test_quant.py
before:
INFO master odoo.service.server: loading test file ./addonss/stock/tests/test_quant.py
after:
WARNING master odoo.service.server: test file ./addonss/stock/tests/test_quant.py cannot be found
- one when the test file is not a python file

In both cases, nothing was being tested but the server did not say why.

closes odoo/odoo#34808

Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
2019-07-12 07:14:38 +00:00
Christophe Simonis dd90919c19 [MERGE] forward port branch saas-12.1 up to d785adba6c 2019-05-17 16:32:26 +02:00
Christophe Simonis 5dbf7bf357 [MERGE] forward port branch saas-12.1 up to f00c490be8 2019-03-26 10:33:26 +01:00
Christophe Simonis 11b1e12cde [MERGE] forward port branch saas-11.3 up to e9068c290b 2019-03-25 18:28:16 +01:00
Christophe Simonis e9068c290b [MERGE] forward port branch 11.0 up to 0196a6feb5 2019-03-25 16:47:05 +01:00
Christophe Simonis 3a0bedd655 [MERGE] forward port branch saas-15 up to 48e4c18fc4 2019-03-22 16:26:33 +01:00
Christophe Simonis 48e4c18fc4 [MERGE] forward port branch saas-14 up to cded89b531 2019-03-22 13:26:19 +01:00
XavierDo a4049296d9 [IMP] core: avoid to process work when worker is 'killed' during sleep.
If a signal is received during the worker _runloop sleep,
the worker will be marked as alive=False but process_work
will still be called once.

This commit prevents that by checking the worker state before
calling process_work.

closes odoo/odoo#31885

Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
2019-03-19 09:43:10 +00:00
Denis Vermylen 744bdd275e [FIX] server.py: stop the FSWatcher when stopping the server
Avoid potential tracebacks from the FSWatcher's thread being killed.

Drawback: Server shut down can have an extra small delay

(only applies when the --dev=reload option is given)

closes odoo/odoo#31855

Signed-off-by: Christophe Simonis <chs@odoo.com>
2019-03-15 14:18:11 +00:00
Denis Vermylen 7b6cfc412e [IMP] server.py: --dev=reload with inotify
Add the alternative of inotify instead of watchdog to watch the addons
paths the server was started with.

Reason: watchdog spawns 2 threads per path to watch. When there are a
lot of addons paths, this can become too costly. With inotify we watch
all the repositories in a single thread.

https://github.com/dsoprea/PyInotify

installation:

    pip install inotify
2019-03-15 14:18:09 +00:00
Denis Vermylen 83b2d2e1b5 [FIX] server.py: don't start multiple FSWatcher in multiworker mode
Before this commit every worker would start his own FSWatcher.
2019-03-14 14:37:57 +00:00
Denis Vermylen a1fa9faa31 [FIX] server.py: FileNotFoundError doesn't exist in P2
Python2 uses IOError instead.

/!\ DO NOT FORWARD PORT AFTER 11.* /!\
2019-03-14 10:06:04 +00:00
Christophe Simonis 8c29df10e0 [MERGE] forward port branch saas-12.1 up to 93d736e905 2019-02-11 17:00:35 +01:00
Christophe Simonis 530f364547 [MERGE] forward port branch saas-11.3 up to 0c42a607ec 2019-02-06 11:59:44 +01:00
Christophe Simonis 9c6acbaaa0 [MERGE] forward port branch 11.0 up to e0b14bf9a7 2019-02-05 17:53:35 +01:00
Xavier Morel 6ce2d6efb5 [FIX] core: allow signal handlers in multiprocess workers
Because Python only runs signal handlers on the main thread, native
calls (IO or accept(2)) can delay these handlers running. This is
especially problematic when one such call is completely stuck and
we're trying to dump the stack to diagnose the issue.

By running the actual worker's processing in a sub-thread and leaving
the main thread sleeping, worker processes should always be able to
handle signals.

closes odoo/odoo#30688
2019-01-30 11:22:05 +00:00
Christophe Monniez de4278c676 [FIX] server: use SIGXCPU on supported platform only
When Odoo is stopped using CTRL+C on Windows, a Traceback is thrown
because the SIGXCPU signal does not exists on Windows.

With this commit, the check for SIGXCPU only occurs on supported
platforms.

Fixes #33311

closes odoo/odoo#33333

Signed-off-by: Christophe Simonis <chs@odoo.com>
2019-05-13 12:39:15 +00:00
Denis Ledoux ec48392e39 [TODO] service/server: note to remove override that will become useless
The method override `_handle_request_noblock`
is there to solve a bug in Python socketserver library
which has been solved in
- Python 3.6: python/cpython@8b1f52b5a9,
- Python 3.7: python/cpython@9080824513,

through PR python/cpython#9952.

These revisions will be included in Python releases 3.6.8 and 3.7.2,
and the override will then become useless.
We therefore can remove the `_handle_request_noblock` override
as soon as the Python 3 releases installed on operating systems
supported by Odoo are above
- 3.6.8 for Python 3.6
- 3.7.2 for Python 3.7

closes odoo/odoo#29706
2018-12-21 11:27:44 +00:00
Christophe Simonis f66a9cdbcf [MERGE] forward port branch 11.0 up to bab5ccfdd7 2018-11-05 17:51:04 +01:00
Olivier Dony 717b7249d5 [FIX] server: always consume wakeup bytes from signals
Due to the implementation of PEP-475[1] in Python 3.5, revision
e98e8e9b1b used the recommended technique
of wakeup file descriptors in order to detect interruption of sleep() and
select() by signals, when running in multi-process mode (workers > 0).

The technique works well, however the initial patch never bothered to
read the byte that is written to the wakeup pipe when a signal is
processed. This does not matter when the signal is meant to shut down
the server, but it matters when the signal is SIGQUIT: it simply prints
thread dumps, and continues operating normally.
As a consequence, that byte remains in the wakeup pipe forever, causing
all the subsequent select/sleep calls to return immediately because
the wakeup fd *is* already ready. The symptom was that worker
processes would start cycling their main run loop very fast after
receiving a SIGQUIT signal, eating 100% CPU.

This patch ensures we always empty the wakeup pipe after an interruptible
call, to avoid this effect. It also refactors another occurrence of the
"empty pipe" pattern, in the PreforkServer, and incidentally uses readable
aliases for the file descriptors bound to the ends of the wakeup pipe
(wakeup_fd_r / wakeup_fd_w).

[1] https://www.python.org/dev/peps/pep-0475

closes odoo/odoo#28356
2018-11-02 11:04:35 +00:00
Christophe Simonis 3b3a65bef0 [MERGE] forward port branch saas-11.4 up to dc35de9d30 2018-11-06 14:12:51 +01:00
Christophe Simonis dc35de9d30 [MERGE] forward port branch saas-11.3 up to f66a9cdbcf 2018-11-06 10:16:30 +01:00
Christophe Simonis a299517f83 [MERGE] forward port branch saas-11.3 up to 6136f0c02e 2018-10-29 11:56:32 +01:00
Christophe Monniez f9ee8cff14 [FIX] tests: avoid remaining requests
From times to times, warning are seen on the runbot during HttpCase
tests with the chrome headless browser.

Those warning are about Odoo trying to join remaining requests threads.
In the dumpstack, the thread seems blocked in the werkzeug
handle_one_request method, when trying to read the HTTP request line.

One explanation could be that Chrome opens a pre-connect socket for
a future use. When the HttpTest cleans the browser, the page stops
loading but (probably) keeps the socket open for a while.

That could explain the problem.

With this commit, a timeout is set on the request handler,
in the hope that it closes the pre-connect socket too.
2018-10-25 17:16:34 +02:00
Christophe Simonis 0fcb28c97b [MERGE] forward port branch saas-11.3 up to d82a907728 2018-10-19 14:32:09 +02:00
Christophe Simonis f2ada1560e [MERGE] forward port branch 11.0 up to 22a13073f0 2018-10-19 12:25:17 +02:00
Christophe Simonis 54db75396f [MERGE] forward port branch saas-14 up to ef670016e6 2018-10-18 15:30:59 +02:00
Christophe Simonis 9c3ec026c5 [MERGE] forward port branch saas-15 up to 54db75396f 2018-10-18 17:16:03 +02:00
Christophe Monniez e0219c7f39 [FIX] tests: avoid remaining requests
From times to times, warning are seen on the runbot during HttpCase
tests with the chrome headless browser.

Those warning are about Odoo trying to join remaining requests threads.
In the dumpstack, the thread seems blocked in the werkzeug
handle_one_request method, when trying to read the HTTP request line.

One explanation could be that Chrome opens a pre-connect socket for
a future use. When the HttpTest cleans the browser, the page stops
loading but (probably) keeps the socket open for a while.

That could explain the problem.

With this commit, a timeout is set on the request handler,
in the hope that it closes the pre-connect socket too.

Cheery-pick of f9ee8cf to avoid runbot_merge failures.

closes odoo/odoo#28193
2018-10-26 11:42:03 +00:00
Christophe Simonis b81c2bce84 [MERGE] forward port branch saas-11.4 up to 3c108977c1 2018-10-22 16:59:51 +02:00
Andreas Raster 956b3ce54d [FIX] server: ignore broken symlinks
Previously broken symlinks would cause a FileNotFoundError
exception in the filesystem watcher thread spawned when using the
--dev=reload argument.

This problem appeared when using emacs to edit python files while
they are being watched by an odoo instance for changes. Emacs
creates a broken symlink as lockfile in the same directory as the
python file that it edits.

This commit makes the filesystem watcher silently ignore any
FileNotFoundError that occurs when it tries to open a file.

Fixes  #21214, closes #21215
2018-10-15 11:15:42 +02:00
Denis Ledoux 3823dcacef [FIX] http, server: cross-platform memory limit management
This revision aims to support the memory limits
on Linux, Windows and MacOSX according to their own spefication
regarding their memory management.

Among others, it brings the possibility to
use the multi-workers mode on Windows and MacOSX.

e.g.
- Windows does not support `resource`,
  and therefore we skip to set the hard limit
- MacOSX allocates a large virtual memory for each process
  even if the memory is not actually used,
  and therefore using the VMS to limit the memory is pointless
  as it will always exceeds the default soft memory limit.
  We therefore choose to use the RSS to limit the memory

closes odoo/odoo#27848
2018-10-16 15:37:40 +00:00
Denis Ledoux b34b7d4270 [FIX] server.py: resource is not available on Windows
Rev. dcb56412d6
introduces limits for the threadedserver

It uses `resource` to set the hard limit,
but unfortunately `resource` is not available on Windows.

As in the GeventServer, we therefore set the resource
hard limit within a `if os.name == 'posix'` block,
as in rev.
c68b41bff2
2018-10-16 12:14:46 +02:00
Denis Ledoux dcb56412d6 [IMP] server.py: implements limits (real) for multi-threading
The multi-threaded server graceful stop policy is now as follows:
 - shutdown the server so it does not accept new requests (the socket remains open),
 - wait for remaining requests to finish up to a certain time (e.g. 1 second)

Previously, the multi-threaded server waited indefinitely for requests to finish.

The reload policy when a thread reaches a limit is as following:
 - wait there is no other running requests, up to 1 minute
 - then stop the server (with the above graceful stop policy applied),
 - then reload the server, therefore accepting new requests again.
- The socket is not closed during this operation.
  This allows the inverse proxy to queue the requests arriving during
  the time the server is shutted down and therefore not accepting new requests.
  This allows a transparent restart for the users, as their
  requests done during the shutting down of the server are not rejected but queued.
- When a thread reaches a limit, we reload the whole threaded server instead of
  just killing this thread. Killing a thread is not a good practice as it could
  lead to dead locks in case these threads acquire locks.
  Killing a thread that acquired a lock would lead for this lock to never be
  released.

Regarding the override of `_handle_request_noblock`:
  In `socketserver`,
  when `shutdown` is called
  `__shutdown_request` is set to True,
  https://github.com/python/cpython/blob/6a7b3a77b4b2be0badd24ee5f0fdbaa2e0e79c3d/Lib/socketserver.py#L241-L249
  This tells the server to no longer accept requests. Callstack below:
  - https://github.com/python/cpython/blob/6a7b3a77b4b2be0badd24ee5f0fdbaa2e0e79c3d/Lib/socketserver.py#L231-L234
  - https://github.com/python/cpython/blob/6a7b3a77b4b2be0badd24ee5f0fdbaa2e0e79c3d/Lib/socketserver.py#L308
  - https://github.com/python/cpython/blob/6a7b3a77b4b2be0badd24ee5f0fdbaa2e0e79c3d/Lib/socketserver.py#L487

  Unfortunately, this is very possible the HTTP server is already polling for a request when this flag is set
  to `True` by the main thread:
  - https://github.com/python/cpython/blob/6a7b3a77b4b2be0badd24ee5f0fdbaa2e0e79c3d/Lib/socketserver.py#L232
  As the poll_interval is set to 0.5s:
  - https://github.com/python/cpython/blob/6a7b3a77b4b2be0badd24ee5f0fdbaa2e0e79c3d/Lib/socketserver.py#L215
  if a request arrives within 500ms after the server is shut down,
  the request is accepted, while the server is shutdown.

  We want to prevent this: Once the server is marked as shut down, we want it to no longer accept requests:
  so the inverse proxy knows it has to queue the request.

closes odoo/odoo#24982
2018-10-15 07:46:52 +00:00