Commit Graph

88 Commits

Author SHA1 Message Date
Max Romanov
3cbc22a6dc Changing router to application port exchange protocol.
The application process needs to request the port from the router instead of the
latter pushing the port before sending a request to the application.  This is
required to simplify the communication between the router and the application
and to prepare the router to use the application shared port and then the queue.
2020-08-11 19:20:10 +03:00
Max Romanov
bf647588ff Adding a reference counter to the libunit port structure.
The goal is to minimize the number of (pid, id) to port hash lookups which
require a library mutex lock.  The response port is found once per request,
while the read port is initialized at startup.
2020-08-11 19:20:06 +03:00
Max Romanov
ec3389b63b Libunit refactoring: port management.
- Changed the port management callbacks to notifications, which e. g. avoids
the need to call the libunit function
- Added context and library instance reference counts for a safer resource
release
- Added the router main port initialization
2020-08-11 19:19:55 +03:00
Valentin Bartenev
f69d470752 Fixed non-debug log time format in libunit.
This makes log format used in libunit consistent with the daemon, where milliseconds are printed only in the
debug log level.

Currently a compile time switch is used, since there's no support for runtime changing of a log level for now.
But in the future this should be a runtime condition, similar to nxt_log_time_handler().
2020-07-21 20:27:37 +03:00
Tiago Natel de Moura
e9e5ddd5a5 Refactor of process management.
The process abstraction has changed to:

  setup(task, process)
  start(task, process_data)
  prefork(task, process, mp)

The prefork() occurs in the main process right before fork.

The file src/nxt_main_process.c is completely free of process
specific logic.

The creation of a process now supports a PROCESS_CREATED state.  The
The setup() function of each process can set its state to either
created or ready.  If created, a MSG_PROCESS_CREATED is sent to main
process, where external setup can be done (required for rootfs under
container).

The core processes (discovery, controller and router) doesn't need
external setup, then they all proceeds to their start() function
straight away.

In the case of applications, the load of the module happens at the
process setup() time and The module's init() function has changed
to be the start() of the process.

The module API has changed to:

  setup(task, process, conf)
  start(task, data)

As a direct benefit of the PROCESS_CREATED message, the clone(2) of
processes using pid namespaces now doesn't need to create a pipe
to make the child block until parent setup uid/gid mappings nor it
needs to receive the child pid.
2020-03-09 16:28:25 +00:00
Max Romanov
58cc13ab29 Resolving a racing condition while adding ports on the app's side.
An earlier attempt (ad6265786871) to resolve this condition on the
router's side added a new issue: the app could get a request before
acquiring a port.
2020-04-10 16:21:58 +03:00
Max Romanov
792ef9d3c7 Fixing 'find & add' racing condition in connected ports hash.
Missing error log messages added.
2020-04-06 16:52:11 +03:00
Max Romanov
0935630cba Fixing application process infinite loop.
Main process exiting before app process init may have caused hanging.
2020-03-30 14:18:51 +03:00
Max Romanov
ab7b42a072 Handling change file message in libunit.
This is required for proper log file rotation action.
2020-03-30 14:18:41 +03:00
Max Romanov
82b899b136 Attributing libunit logging function for arguments validation. 2020-03-30 14:08:20 +03:00
Max Romanov
5296be0b82 Using disk file to store large request body.
This closes #386 on GitHub.
2020-03-12 17:54:29 +03:00
Max Romanov
2454dfe876 Introducing readline function in libunit.
Ruby and Java modules now use this function instead of own
implementations.
2020-03-12 17:54:05 +03:00
Max Romanov
7c38650cd1 Removing duplicate macro definitions.
This issue was introduced in 2c7f79bf0a1f.
2020-02-04 11:39:16 +03:00
Max Romanov
8eba2e5c3d Initializing local buffer ctx_impl field for correct release.
Uninitialized ctx_impl field may cause crash in application process.

To reproduce the issue, need to trigger shared memory buffer send error on
application side.  In our case, send error caused by router process crash.

This issue was introduced in 2c7f79bf0a1f.
2020-02-03 11:21:21 +03:00
Max Romanov
51120e06e3 Added missing stream argument to error message.
Found by Coverity (CID 353386).
2020-02-03 11:14:06 +03:00
Max Romanov
df7caf4650 Introducing port messages to notify about out of shared memory.
- OOSM (out of shared memory).  Sent by application process to router
  when application reaches the limit of allocated shared memory and
  needs more.
- SHM_ACK.  Sent by router to application when the application's shared
  memory is released and the OOSM flag is enabled for the segment.

This implements blocking mode (the library waits for SHM_ACK in case of
out of shared memory condition and retries allocating the required memory
amount) and non-blocking mode (the library notifies the application that
it's out of shared memory and returns control to the application module
that sets up the output queue and puts SHM_ACK in the main message loop).
2019-12-24 18:04:13 +03:00
Max Romanov
64f649f990 Adding "limits/shm" configuration validation and parsing. 2019-12-24 18:04:09 +03:00
Max Romanov
429c5a1c54 Renaming nxt_unit_mmap_buf_remove to nxt_unit_mmap_buf_unlink.
The function unchains the buffer from the buffer's linked list.
2019-12-24 18:04:05 +03:00
Max Romanov
faeb73a65e Using non-shared memory buffers for small messages.
Current shared memory buffer implementation uses fixed-size memory blocks,
allocating at least 16384 bytes.  When application sends data in a large
number of small chunks, it makes sense to buffer them or use plain
memory buffers to improve performance and reduce memory footprint.

This patch introduces minimum size limit (1024 bytes) for shared
memory buffers.
2019-12-24 18:03:56 +03:00
Max Romanov
f2610d2160 Fixing libunit 'off by 2' issue in library.
Name and value in each header are 0-terminated, so additional 2 bytes
should be allocated for them.  There were several attempts to add these
2 bytes to headers in language modules, but some modules weren't updated.
Also, adding these 2 bytes is specific to the implementation which may be
changed later, so extending this mechanics to modules may cause errors.
2019-11-11 18:04:17 +03:00
Igor Sysoev
09e7357b08 Style fixes. 2019-10-10 19:42:41 +03:00
Tiago de Bem Natel de Moura
c554941b4f Initial applications isolation support using Linux namespaces. 2019-09-19 15:25:23 +03:00
Max Romanov
6346e641ee Releasing WebSocket frame in case of buffer allocation failure.
Found by Coverity (CID 349456).
2019-09-19 16:28:03 +03:00
Max Romanov
a216b15e99 Fixing request release order to avoid crashes on exit.
Each request references the router process structure that owns all memory
maps.  The process structure has a reference counter; each request increases
the counter to lock the structure in memory until request processing ends.
Incoming and outgoing buffers reference memory maps that the process owns,
so the process structure should be released only when all buffers are
released to avoid invalid memory access and a crash.

This describes the libunit library mechanism used for application processes.

The background of this issue is as follows:

The issue was found on buildbot when the router crashed during Java
websocket tests.  The Java application receives a notification from the
master process; when the notification is processed, libunit deletes the
process structure from its process hash and decrements the use counter;
however, active websocket connections maintain their use counts on the
process structure.  After that, when the master process is stopping the
application, libunit releases active websocket connections.  At this point,
it's important to release the connections' memory buffers before the
corresponding process structure and all shared memory segments are released.
2019-09-18 18:31:22 +03:00
Max Romanov
4ea9ed309e Reducing number of warning messages.
One alert per failed allocation is enough.
2019-09-18 18:31:06 +03:00
Max Romanov
9bacd21405 Protecting context structures with mutex.
By design, Unit context is created for the thread which reads messages from
the router.  However, Go request handlers are called in a separate goroutine
that may be executed in a different thread.  To avoid a racing condition,
access to lists of free structures in the context should be serialized.  This
patch should fix random crashes in Go applications under high load.

This is related to #253 and #309 issues on GitHub.
2019-09-18 18:30:58 +03:00
Max Romanov
e501c74ddc Introducing websocket support in router and libunit. 2019-08-20 16:31:53 +03:00
Andrey Zelenkov
22de5fcddf Style. 2019-03-11 17:31:59 +03:00
Max Romanov
ec7319d32c Various libunit fixes.
This patch contains various logging improvements and bugfixes found
during Java module development.
2019-02-28 15:52:36 +03:00
Valentin Bartenev
e929d08201 Fixed processing of SERVER_NAME after 77aad2c142a0.
Previously, the nxt_router_prepare_msg() function expected server host among
other headers unmodified.  It's not true anymore since normalization of the
Host header has been introduced in 77aad2c142a0.

The nxt_unit_split_host() function was removed.  It didn't work correctly with
IPv6 literals.  Anyway, after 77aad2c142a0 the port splitting is done in router
while Host header processing.
2019-02-27 17:25:07 +03:00
Sergey Kandaurov
3280b826e3 Initializing incoming buffer queue in a proper place.
In case nxt_unit_tracking_read() failed, execution would jump to the error path,
where it could try to release buffers from uninitialized yet incoming_buf queue.
2019-02-21 16:30:59 +03:00
Alexander Borisov
c838c3bd15 Node.js: added async request execution. 2018-10-31 15:51:51 +03:00
Max Romanov
141ee2aa32 Filling cmsghdr with 0 to pass Go 1.11 message validation. 2018-10-02 19:49:49 +03:00
Max Romanov
cb1b074493 Making port fd blocking on app side and non-blocking in Unit.
This issue was introduced in libunit commit (e0f0cd7d244a).  All port
sockets in application should be in blocking mode whereas Unit itself
operates non-blocking sockets.

Having non-blocking sockets in application may cause send error during
intensive response packets generation.

See https://mailman.nginx.org/pipermail/unit/2018-October/000080.html.
2018-10-02 19:46:06 +03:00
Max Romanov
b2ec830515 Removing non-required warning. 2018-08-07 20:03:58 +03:00
Max Romanov
9015b8b25d Improved 'invalid file descriptor' diagnostic.
Unit router process may send mmap file decritptor to the application process
for further information exchange.  During this process there may be various
errors, which should be described in application error log.  If file descriptor
cannot be properly transferred with 'new mmap' message, fd variable will
be assigned to -1 and further syscalls using this file descriptor will fail.

For 'new port' message fd is checked in the same way.

This commit adds early 'invalid file descriptor' diagnostic and write
corresponding message to error log.

Found by Coverity (CID 308515).
2018-08-07 17:57:06 +03:00
Max Romanov
257283cc38 Fixed unit library mutex usage.
For the optimization purpose, function nxt_unit_remove_process() expects
lib->mutex to be locked.  The function then moves ports queue into temporary
queue and releases mutex.  In nxt_unit_done() there were two errors: mutex was
not locked before nxt_unit_remove_process() call and mutex was not destroyed.
It is hard to tell what was possible negative impact of this errors.

Found by Coverity (CID 308517).
2018-08-07 15:52:11 +03:00
Max Romanov
1bb22d1e92 Unit application library.
Library now used in all language modules.
Old 'nxt_app_*' code removed.

See src/test/nxt_unit_app_test.c for usage sample.
2018-08-06 17:27:33 +03:00