Mercurial > hg > nginx
annotate src/os/unix/ngx_shmem.c @ 7948:a2613fc1bce5
Fixed sendfile() limit handling on Linux.
On Linux starting with 2.6.16, sendfile() silently limits all operations
to MAX_RW_COUNT, defined as (INT_MAX & PAGE_MASK). This incorrectly
triggered the interrupt check, and resulted in 0-sized writev() on the
next loop iteration.
Fix is to make sure the limit is always checked, so we will return from
the loop if the limit is already reached even if number of bytes sent is
not exactly equal to the number of bytes we've tried to send.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 29 Oct 2021 20:21:51 +0300 |
parents | d620f497c50f |
children |
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:
358
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:
358
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 | 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:
358
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:
358
diff
changeset
|
6 |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
11 |
469 | 12 #if (NGX_HAVE_MAP_ANON) |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
13 |
605 | 14 ngx_int_t |
15 ngx_shm_alloc(ngx_shm_t *shm) | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
16 { |
639 | 17 shm->addr = (u_char *) mmap(NULL, shm->size, |
18 PROT_READ|PROT_WRITE, | |
19 MAP_ANON|MAP_SHARED, -1, 0); | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
20 |
605 | 21 if (shm->addr == MAP_FAILED) { |
22 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, | |
23 "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size); | |
24 return NGX_ERROR; | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
25 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
26 |
605 | 27 return NGX_OK; |
28 } | |
29 | |
30 | |
31 void | |
32 ngx_shm_free(ngx_shm_t *shm) | |
33 { | |
639 | 34 if (munmap((void *) shm->addr, shm->size) == -1) { |
605 | 35 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, |
36 "munmap(%p, %uz) failed", shm->addr, shm->size); | |
37 } | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
38 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
39 |
469 | 40 #elif (NGX_HAVE_MAP_DEVZERO) |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
41 |
605 | 42 ngx_int_t |
43 ngx_shm_alloc(ngx_shm_t *shm) | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
44 { |
605 | 45 ngx_fd_t fd; |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
46 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
47 fd = open("/dev/zero", O_RDWR); |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
48 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
49 if (fd == -1) { |
605 | 50 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, |
467 | 51 "open(\"/dev/zero\") failed"); |
605 | 52 return NGX_ERROR; |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
53 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
54 |
639 | 55 shm->addr = (u_char *) mmap(NULL, shm->size, PROT_READ|PROT_WRITE, |
56 MAP_SHARED, fd, 0); | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
57 |
605 | 58 if (shm->addr == MAP_FAILED) { |
59 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, | |
60 "mmap(/dev/zero, MAP_SHARED, %uz) failed", shm->size); | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
61 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
62 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
63 if (close(fd) == -1) { |
605 | 64 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, |
467 | 65 "close(\"/dev/zero\") failed"); |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
66 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
67 |
605 | 68 return (shm->addr == MAP_FAILED) ? NGX_ERROR : NGX_OK; |
69 } | |
70 | |
71 | |
72 void | |
73 ngx_shm_free(ngx_shm_t *shm) | |
74 { | |
639 | 75 if (munmap((void *) shm->addr, shm->size) == -1) { |
605 | 76 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, |
77 "munmap(%p, %uz) failed", shm->addr, shm->size); | |
78 } | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
79 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
80 |
469 | 81 #elif (NGX_HAVE_SYSVSHM) |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
82 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
83 #include <sys/ipc.h> |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
84 #include <sys/shm.h> |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
85 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
86 |
605 | 87 ngx_int_t |
88 ngx_shm_alloc(ngx_shm_t *shm) | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
89 { |
605 | 90 int id; |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
91 |
605 | 92 id = shmget(IPC_PRIVATE, shm->size, (SHM_R|SHM_W|IPC_CREAT)); |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
93 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
94 if (id == -1) { |
605 | 95 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, |
96 "shmget(%uz) failed", shm->size); | |
97 return NGX_ERROR; | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
98 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
99 |
605 | 100 ngx_log_debug1(NGX_LOG_DEBUG_CORE, shm->log, 0, "shmget id: %d", id); |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
101 |
605 | 102 shm->addr = shmat(id, NULL, 0); |
103 | |
104 if (shm->addr == (void *) -1) { | |
105 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "shmat() failed"); | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
106 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
107 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
108 if (shmctl(id, IPC_RMID, NULL) == -1) { |
605 | 109 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, |
110 "shmctl(IPC_RMID) failed"); | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
111 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
112 |
605 | 113 return (shm->addr == (void *) -1) ? NGX_ERROR : NGX_OK; |
114 } | |
115 | |
116 | |
117 void | |
118 ngx_shm_free(ngx_shm_t *shm) | |
119 { | |
120 if (shmdt(shm->addr) == -1) { | |
121 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, | |
122 "shmdt(%p) failed", shm->addr); | |
123 } | |
358
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
124 } |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
125 |
0a03c921c81d
nginx-0.0.7-2004-06-17-21:18:53 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
126 #endif |