annotate src/os/unix/ngx_daemon.c @ 9277:4a0cd107c0f1 default tip

HTTP/2: handling of connections initialized during shutdown. If an HTTP/2 connection opened before a graceful shutdown, but ngx_http_v2_init() is called after idle connections were closed, such a connection ended up being open till closed by the client (or up to keepalive_time), delaying shutdown. With this change, such connections are allowed to serve just one request, much like it happens in HTTP/1.x, and closed afterwards. Reported by Kasei Wang, https://freenginx.org/pipermail/nginx-devel/2024-May/000277.html
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 28 May 2024 20:43:50 +0300
parents 3d455e37abf8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
441
da8c5707af39 nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents: 249
diff changeset
1
da8c5707af39 nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents: 249
diff changeset
2 /*
444
42d11f017717 nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents: 441
diff changeset
3 * Copyright (C) Igor Sysoev
4412
d620f497c50f Copyright updated.
Maxim Konovalov <maxim@nginx.com>
parents: 499
diff changeset
4 * Copyright (C) Nginx, Inc.
441
da8c5707af39 nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents: 249
diff changeset
5 */
da8c5707af39 nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents: 249
diff changeset
6
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
7
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
8 #include <ngx_config.h>
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
9 #include <ngx_core.h>
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
10
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
11
9270
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
12 static ngx_fd_t ngx_daemon_fd = NGX_INVALID_FILE;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
13
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
14
4574
b1ba43f905f8 Style: the function type should be on a line by itself
Maxim Konovalov <maxim@nginx.com>
parents: 4412
diff changeset
15 ngx_int_t
b1ba43f905f8 Style: the function type should be on a line by itself
Maxim Konovalov <maxim@nginx.com>
parents: 4412
diff changeset
16 ngx_daemon(ngx_log_t *log)
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
17 {
9270
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
18 u_char buf[1];
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
19 ssize_t n;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
20 ngx_fd_t fd, pp[2];
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
21
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
22 if (pipe(pp) == -1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
23 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "pipe() failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
24 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
25 }
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
26
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
27 switch (fork()) {
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
28 case -1:
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
29 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
30 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
31
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
32 case 0:
9270
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
33 if (close(pp[0]) == -1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
34 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() pipe failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
35 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
36 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
37
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
38 ngx_daemon_fd = pp[1];
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
39 break;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
40
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
41 default:
9270
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
42 if (close(pp[1]) == -1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
43 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() pipe failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
44 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
45 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
46
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
47 n = read(pp[0], buf, 1);
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
48
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
49 if (n == 0) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
50 /* child exited */
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
51 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
52 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
53
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
54 if (n != 1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
55 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
56 "read() pipe failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
57 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
58 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
59
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
60 if (close(pp[0]) == -1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
61 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() pipe failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
62 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
63 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
64
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
65 exit(0);
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
66 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
67
7162
8b84d60ef13d Fixed "changing binary" when reaper is not init.
Ruslan Ermilov <ru@nginx.com>
parents: 4574
diff changeset
68 ngx_parent = ngx_pid;
249
2a0540287298 nginx-0.0.2-2004-02-03-19:43:54 import
Igor Sysoev <igor@sysoev.ru>
parents: 191
diff changeset
69 ngx_pid = ngx_getpid();
2a0540287298 nginx-0.0.2-2004-02-03-19:43:54 import
Igor Sysoev <igor@sysoev.ru>
parents: 191
diff changeset
70
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
71 if (setsid() == -1) {
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
72 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
73 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
74 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
75
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
76 umask(0);
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
77
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
78 fd = open("/dev/null", O_RDWR);
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
79 if (fd == -1) {
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
80 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
81 "open(\"/dev/null\") failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
82 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
83 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
84
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
85 if (dup2(fd, STDIN_FILENO) == -1) {
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
86 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
87 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
88 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
89
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
90 if (dup2(fd, STDOUT_FILENO) == -1) {
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
91 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
92 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
93 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
94
105
00bee6e7b485 nginx-0.0.1-2003-06-15-22:32:13 import
Igor Sysoev <igor@sysoev.ru>
parents: 92
diff changeset
95 #if 0
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
96 if (dup2(fd, STDERR_FILENO) == -1) {
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
97 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
98 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
99 }
105
00bee6e7b485 nginx-0.0.1-2003-06-15-22:32:13 import
Igor Sysoev <igor@sysoev.ru>
parents: 92
diff changeset
100 #endif
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
101
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
102 if (fd > STDERR_FILENO) {
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
103 if (close(fd) == -1) {
191
71ce40b3c37b nginx-0.0.1-2003-11-19-19:26:41 import
Igor Sysoev <igor@sysoev.ru>
parents: 105
diff changeset
104 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
86
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
105 return NGX_ERROR;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
106 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
107 }
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
108
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
109 return NGX_OK;
3973260705cc nginx-0.0.1-2003-05-12-19:52:24 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff changeset
110 }
9270
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
111
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
112
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
113 ngx_int_t
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
114 ngx_daemon_sync(ngx_log_t *log)
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
115 {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
116 if (ngx_daemon_fd == NGX_INVALID_FILE) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
117 return NGX_OK;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
118 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
119
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
120 if (write(ngx_daemon_fd, "", 1) != 1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
121 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "write() pipe failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
122 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
123 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
124
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
125 if (close(ngx_daemon_fd) == -1) {
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
126 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() pipe failed");
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
127 return NGX_ERROR;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
128 }
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
129
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
130 ngx_daemon_fd = NGX_INVALID_FILE;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
131
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
132 return NGX_OK;
3d455e37abf8 Core: PID file writing synchronization.
Maxim Dounin <mdounin@mdounin.ru>
parents: 7162
diff changeset
133 }