Skip to content

Commit 766c7f9

Browse files
author
Sascha Schumann
committed
Serialize headers for systems with low IOV_MAX (e.g. Solaris)
1 parent c013462 commit 766c7f9

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

sapi/thttpd/thttpd.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,20 @@ static int sapi_thttpd_ub_write(const char *str, uint str_length TSRMLS_DC)
9393
return sent;
9494
}
9595

96-
#define ADD_VEC(str,l) vec[n].iov_base=str;len += (vec[n].iov_len=l); n++
97-
#define ADD_VEC_S(str) ADD_VEC((str), sizeof(str)-1)
98-
#define COMBINE_HEADERS 30
96+
#define COMBINE_HEADERS 64
97+
98+
#if defined(IOV_MAX)
99+
# if IOV_MAX - 64 <= 0
100+
# define SERIALIZE_HEADERS
101+
# endif
102+
#endif
99103

100104
static int do_writev(struct iovec *vec, int nvec, int len TSRMLS_DC)
101105
{
102106
int n;
103107

104-
/*
105-
* XXX: partial writevs are not handled
106-
* This can only cause problems, if the user tries to send
107-
* huge headers, so I consider this a void issue right now.
108-
* The maximum size depends on SO_SNDBUF and is usually
109-
* at least 16KB from my experience.
110-
*/
111-
108+
assert(nvec <= IOV_MAX);
109+
112110
if (TG(sbuf).c == 0) {
113111
n = writev(TG(hc)->conn_fd, vec, nvec);
114112

@@ -151,6 +149,18 @@ static int do_writev(struct iovec *vec, int nvec, int len TSRMLS_DC)
151149
return 0;
152150
}
153151

152+
#ifdef SERIALIZE_HEADERS
153+
# define ADD_VEC(str,l) smart_str_appendl(&vec_str, (str), (l))
154+
# define VEC_BASE() smart_str vec_str = {0}
155+
# define VEC_FREE() smart_str_free(&vec_str)
156+
#else
157+
# define ADD_VEC(str,l) vec[n].iov_base=str;len += (vec[n].iov_len=l); n++
158+
# define VEC_BASE() struct iovec vec[COMBINE_HEADERS]
159+
# define VEC_FREE() do {} while (0)
160+
#endif
161+
162+
#define ADD_VEC_S(str) ADD_VEC((str), sizeof(str)-1)
163+
154164
#define CL_TOKEN "Content-length: "
155165
#define CN_TOKEN "Connection: "
156166
#define KA_DO "Connection: keep-alive\r\n"
@@ -160,8 +170,7 @@ static int do_writev(struct iovec *vec, int nvec, int len TSRMLS_DC)
160170
static int sapi_thttpd_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
161171
{
162172
char buf[1024], *p;
163-
struct iovec vec[COMBINE_HEADERS];
164-
173+
VEC_BASE();
165174
int n = 0;
166175
zend_llist_position pos;
167176
sapi_header_struct *h;
@@ -197,10 +206,12 @@ static int sapi_thttpd_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
197206
}
198207

199208
ADD_VEC(h->header, h->header_len);
209+
#ifndef SERIALIZE_HEADERS
200210
if (n >= COMBINE_HEADERS - 1) {
201211
len = do_writev(vec, n, len TSRMLS_CC);
202212
n = 0;
203213
}
214+
#endif
204215
ADD_VEC("\r\n", 2);
205216

206217
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
@@ -214,8 +225,14 @@ static int sapi_thttpd_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
214225
}
215226

216227
ADD_VEC("\r\n", 2);
217-
228+
229+
#ifdef SERIALIZE_HEADERS
230+
sapi_thttpd_ub_write(vec_str.c, vec_str.len TSRMLS_CC);
231+
#else
218232
do_writev(vec, n, len TSRMLS_CC);
233+
#endif
234+
235+
VEC_FREE();
219236

220237
return SAPI_HEADER_SENT_SUCCESSFULLY;
221238
}

0 commit comments

Comments
 (0)