Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit80788a4

Browse files
committed
Simplify waiting logic in reading from / writing to client.
The client socket is always in non-blocking mode, and if we actually wantblocking behaviour, we emulate it by sleeping and retrying. But we haveretry loops at different layers for reads and writes, which was confusing.To simplify, remove all the sleeping and retrying code from the lowerlevels, from be_tls_read and secure_raw_read and secure_raw_write, and putall the logic in secure_read() and secure_write().
1 parent272923a commit80788a4

File tree

4 files changed

+79
-152
lines changed

4 files changed

+79
-152
lines changed

‎src/backend/libpq/be-secure-openssl.c

Lines changed: 18 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -511,14 +511,11 @@ be_tls_close(Port *port)
511511
*Read data from a secure connection.
512512
*/
513513
ssize_t
514-
be_tls_read(Port*port,void*ptr,size_tlen)
514+
be_tls_read(Port*port,void*ptr,size_tlen,int*waitfor)
515515
{
516516
ssize_tn;
517517
interr;
518-
intwaitfor;
519-
intlatchret;
520518

521-
rloop:
522519
errno=0;
523520
n=SSL_read(port->ssl,ptr,len);
524521
err=SSL_get_error(port->ssl,n);
@@ -528,39 +525,15 @@ be_tls_read(Port *port, void *ptr, size_t len)
528525
port->count+=n;
529526
break;
530527
caseSSL_ERROR_WANT_READ:
528+
*waitfor=WL_SOCKET_READABLE;
529+
errno=EWOULDBLOCK;
530+
n=-1;
531+
break;
531532
caseSSL_ERROR_WANT_WRITE:
532-
/* Don't retry if the socket is in nonblocking mode. */
533-
if (port->noblock)
534-
{
535-
errno=EWOULDBLOCK;
536-
n=-1;
537-
break;
538-
}
539-
540-
waitfor=WL_LATCH_SET;
541-
542-
if (err==SSL_ERROR_WANT_READ)
543-
waitfor |=WL_SOCKET_READABLE;
544-
else
545-
waitfor |=WL_SOCKET_WRITEABLE;
546-
547-
latchret=WaitLatchOrSocket(MyLatch,waitfor,port->sock,0);
548-
549-
/*
550-
* We'll, among other situations, get here if the low level
551-
* routine doing the actual recv() via the socket got interrupted
552-
* by a signal. That's so we can handle interrupts once outside
553-
* openssl, so we don't jump out from underneath its covers. We
554-
* can check this both, when reading and writing, because even
555-
* when writing that's just openssl's doing, not a 'proper' write
556-
* initiated by postgres.
557-
*/
558-
if (latchret&WL_LATCH_SET)
559-
{
560-
ResetLatch(MyLatch);
561-
ProcessClientReadInterrupt(true);/* preserves errno */
562-
}
563-
gotorloop;
533+
*waitfor=WL_SOCKET_WRITEABLE;
534+
errno=EWOULDBLOCK;
535+
n=-1;
536+
break;
564537
caseSSL_ERROR_SYSCALL:
565538
/* leave it to caller to ereport the value of errno */
566539
if (n!=-1)
@@ -595,12 +568,10 @@ be_tls_read(Port *port, void *ptr, size_t len)
595568
*Write data to a secure connection.
596569
*/
597570
ssize_t
598-
be_tls_write(Port*port,void*ptr,size_tlen)
571+
be_tls_write(Port*port,void*ptr,size_tlen,int*waitfor)
599572
{
600573
ssize_tn;
601574
interr;
602-
intwaitfor;
603-
intlatchret;
604575

605576
/*
606577
* If SSL renegotiations are enabled and we're getting close to the
@@ -630,7 +601,6 @@ be_tls_write(Port *port, void *ptr, size_t len)
630601
errmsg("SSL failure during renegotiation start")));
631602
}
632603

633-
wloop:
634604
errno=0;
635605
n=SSL_write(port->ssl,ptr,len);
636606
err=SSL_get_error(port->ssl,n);
@@ -640,30 +610,15 @@ be_tls_write(Port *port, void *ptr, size_t len)
640610
port->count+=n;
641611
break;
642612
caseSSL_ERROR_WANT_READ:
613+
*waitfor=WL_SOCKET_READABLE;
614+
errno=EWOULDBLOCK;
615+
n=-1;
616+
break;
643617
caseSSL_ERROR_WANT_WRITE:
644-
645-
waitfor=WL_LATCH_SET;
646-
647-
if (err==SSL_ERROR_WANT_READ)
648-
waitfor |=WL_SOCKET_READABLE;
649-
else
650-
waitfor |=WL_SOCKET_WRITEABLE;
651-
652-
latchret=WaitLatchOrSocket(MyLatch,waitfor,port->sock,0);
653-
654-
/*
655-
* Check for interrupts here, in addition to secure_write(),
656-
* because an interrupted write in secure_raw_write() will return
657-
* here, and we cannot return to secure_write() until we've
658-
* written something.
659-
*/
660-
if (latchret&WL_LATCH_SET)
661-
{
662-
ResetLatch(MyLatch);
663-
ProcessClientWriteInterrupt(true);/* preserves errno */
664-
}
665-
666-
gotowloop;
618+
*waitfor=WL_SOCKET_WRITEABLE;
619+
errno=EWOULDBLOCK;
620+
n=-1;
621+
break;
667622
caseSSL_ERROR_SYSCALL:
668623
/* leave it to caller to ereport the value of errno */
669624
if (n!=-1)

‎src/backend/libpq/be-secure.c

Lines changed: 57 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -127,30 +127,45 @@ ssize_t
127127
secure_read(Port*port,void*ptr,size_tlen)
128128
{
129129
ssize_tn;
130+
intwaitfor;
130131

131132
retry:
132133
#ifdefUSE_SSL
134+
waitfor=0;
133135
if (port->ssl_in_use)
134136
{
135-
n=be_tls_read(port,ptr,len);
137+
n=be_tls_read(port,ptr,len,&waitfor);
136138
}
137139
else
138140
#endif
139141
{
140142
n=secure_raw_read(port,ptr,len);
143+
waitfor=WL_SOCKET_READABLE;
141144
}
142145

143-
/*retry after processing interrupts */
144-
if (n<0&&errno==EINTR)
146+
/*In blocking mode, wait until the socket is ready */
147+
if (n<0&&!port->noblock&& (errno==EWOULDBLOCK||errno==EAGAIN))
145148
{
146-
/*
147-
* We tried to read data, the socket was empty, and we were
148-
* interrupted while waiting for readability. We only process
149-
* interrupts if we got interrupted while reading and when in blocking
150-
* mode. In other cases it's better to allow the interrupts to be
151-
* handled at higher layers.
152-
*/
153-
ProcessClientReadInterrupt(!port->noblock);/* preserves errno */
149+
intw;
150+
151+
Assert(waitfor);
152+
153+
w=WaitLatchOrSocket(MyLatch,
154+
WL_LATCH_SET |waitfor,
155+
port->sock,0);
156+
157+
/* Handle interrupt. */
158+
if (w&WL_LATCH_SET)
159+
{
160+
ResetLatch(MyLatch);
161+
ProcessClientReadInterrupt(true);
162+
163+
/*
164+
* We'll retry the read. Most likely it will return immediately
165+
* because there's still no data available, and we'll wait
166+
* for the socket to become ready again.
167+
*/
168+
}
154169
gotoretry;
155170
}
156171

@@ -173,7 +188,6 @@ secure_raw_read(Port *port, void *ptr, size_t len)
173188
* Try to read from the socket without blocking. If it succeeds we're
174189
* done, otherwise we'll wait for the socket using the latch mechanism.
175190
*/
176-
rloop:
177191
#ifdefWIN32
178192
pgwin32_noblock= true;
179193
#endif
@@ -182,37 +196,6 @@ secure_raw_read(Port *port, void *ptr, size_t len)
182196
pgwin32_noblock= false;
183197
#endif
184198

185-
if (n<0&& !port->noblock&& (errno==EWOULDBLOCK||errno==EAGAIN))
186-
{
187-
intw;
188-
intsave_errno=errno;
189-
190-
w=WaitLatchOrSocket(MyLatch,
191-
WL_LATCH_SET |WL_SOCKET_READABLE,
192-
port->sock,0);
193-
194-
if (w&WL_LATCH_SET)
195-
{
196-
ResetLatch(MyLatch);
197-
/*
198-
* Force a return, so interrupts can be processed when not
199-
* (possibly) underneath a ssl library.
200-
*/
201-
errno=EINTR;
202-
return-1;
203-
}
204-
elseif (w&WL_SOCKET_READABLE)
205-
{
206-
gotorloop;
207-
}
208-
209-
/*
210-
* Restore errno, clobbered by WaitLatchOrSocket, so the caller can
211-
* react properly.
212-
*/
213-
errno=save_errno;
214-
}
215-
216199
returnn;
217200
}
218201

@@ -224,33 +207,54 @@ ssize_t
224207
secure_write(Port*port,void*ptr,size_tlen)
225208
{
226209
ssize_tn;
210+
intwaitfor;
227211

228212
retry:
213+
waitfor=0;
229214
#ifdefUSE_SSL
230215
if (port->ssl_in_use)
231216
{
232-
n=be_tls_write(port,ptr,len);
217+
n=be_tls_write(port,ptr,len,&waitfor);
233218
}
234219
else
235220
#endif
236221
{
237222
n=secure_raw_write(port,ptr,len);
223+
waitfor=WL_SOCKET_WRITEABLE;
238224
}
239225

240-
/* retry after processing interrupts */
241-
if (n<0&&errno==EINTR)
226+
if (n<0&& !port->noblock&& (errno==EWOULDBLOCK||errno==EAGAIN))
242227
{
243-
/*
244-
* We tried to send data, the socket was full, and we were interrupted
245-
* while waiting for writability. We only process interrupts if we got
246-
* interrupted while writing and when in blocking mode. In other cases
247-
* it's better to allow the interrupts to be handled at higher layers.
248-
*/
249-
ProcessClientWriteInterrupt(!port->noblock);
228+
intw;
229+
230+
Assert(waitfor);
250231

232+
w=WaitLatchOrSocket(MyLatch,
233+
WL_LATCH_SET |waitfor,
234+
port->sock,0);
235+
236+
/* Handle interrupt. */
237+
if (w&WL_LATCH_SET)
238+
{
239+
ResetLatch(MyLatch);
240+
ProcessClientWriteInterrupt(true);
241+
242+
/*
243+
* We'll retry the write. Most likely it will return immediately
244+
* because there's still no data available, and we'll wait
245+
* for the socket to become ready again.
246+
*/
247+
}
251248
gotoretry;
252249
}
253250

251+
/*
252+
* Process interrupts that happened while (or before) sending. Note that
253+
* we signal that we're not blocking, which will prevent some types of
254+
* interrupts from being processed.
255+
*/
256+
ProcessClientWriteInterrupt(false);
257+
254258
returnn;
255259
}
256260

@@ -259,8 +263,6 @@ secure_raw_write(Port *port, const void *ptr, size_t len)
259263
{
260264
ssize_tn;
261265

262-
wloop:
263-
264266
#ifdefWIN32
265267
pgwin32_noblock= true;
266268
#endif
@@ -269,36 +271,5 @@ secure_raw_write(Port *port, const void *ptr, size_t len)
269271
pgwin32_noblock= false;
270272
#endif
271273

272-
if (n<0&& !port->noblock&& (errno==EWOULDBLOCK||errno==EAGAIN))
273-
{
274-
intw;
275-
intsave_errno=errno;
276-
277-
w=WaitLatchOrSocket(MyLatch,
278-
WL_LATCH_SET |WL_SOCKET_WRITEABLE,
279-
port->sock,0);
280-
281-
if (w&WL_LATCH_SET)
282-
{
283-
ResetLatch(MyLatch);
284-
/*
285-
* Force a return, so interrupts can be processed when not
286-
* (possibly) underneath a ssl library.
287-
*/
288-
errno=EINTR;
289-
return-1;
290-
}
291-
elseif (w&WL_SOCKET_WRITEABLE)
292-
{
293-
gotowloop;
294-
}
295-
296-
/*
297-
* Restore errno, clobbered by WaitLatchOrSocket, so the caller can
298-
* react properly.
299-
*/
300-
errno=save_errno;
301-
}
302-
303274
returnn;
304275
}

‎src/backend/libpq/pqcomm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ pq_init(void)
185185
/*
186186
* In backends (as soon as forked) we operate the underlying socket in
187187
* nonblocking mode and use latches to implement blocking semantics if
188-
* needed. That allows us to provide safely interruptible reads.
188+
* needed. That allows us to provide safely interruptible reads and
189+
* writes.
189190
*
190191
* Use COMMERROR on failure, because ERROR would try to send the error to
191192
* the client, which might require changing the mode again, leading to

‎src/include/libpq/libpq-be.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ typedef struct Port
209209
externvoidbe_tls_init(void);
210210
externintbe_tls_open_server(Port*port);
211211
externvoidbe_tls_close(Port*port);
212-
externssize_tbe_tls_read(Port*port,void*ptr,size_tlen);
213-
externssize_tbe_tls_write(Port*port,void*ptr,size_tlen);
212+
externssize_tbe_tls_read(Port*port,void*ptr,size_tlen,int*waitfor);
213+
externssize_tbe_tls_write(Port*port,void*ptr,size_tlen,int*waitfor);
214214

215215
#endif
216216

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp