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

Commite507e08

Browse files
committed
oauth: Remove expired timers from the multiplexer
In a case similar to the previous commit, an expired timer can remainpermanently readable if Curl does not remove the timeout itself. Sincethat removal isn't guaranteed to happen in real-world situations,implement drain_timer_events() to reset the timer before calling intodrive_request().Moving to drain_timer_events() happens to fix a logic bug in theprevious caller of timer_expired(), which treated an error condition asif the timer were expired instead of bailing out.The previous implementation of timer_expired() gave differing resultsfor epoll and kqueue if the timer was reset. (For epoll, a reset timerwas considered to be expired, and for kqueue it was not.) This didn'tpreviously cause problems, since timer_expired() was only called whilethe timer was known to be set, but both implementations now use thekqueue logic.Reviewed-by: Thomas Munro <thomas.munro@gmail.com>Backpatch-through: 18Discussion:https://postgr.es/m/CAOYmi+nDZxJHaWj9_jRSyf8uMToCADAmOfJEggsKW-kY7aUwHA@mail.gmail.com
1 parent16b0c48 commite507e08

File tree

1 file changed

+68
-40
lines changed

1 file changed

+68
-40
lines changed

‎src/interfaces/libpq-oauth/oauth-curl.c‎

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,40 +1536,20 @@ set_timer(struct async_ctx *actx, long timeout)
15361536

15371537
/*
15381538
* Returns 1 if the timeout in the multiplexer set has expired since the last
1539-
* call to set_timer(), 0 if the timer is still running, or-1 (with an
1540-
* actx_error() report) if the timer cannot be queried.
1539+
* call to set_timer(), 0 if the timer iseitherstill running ordisarmed, or
1540+
*-1 (with anactx_error() report) if the timer cannot be queried.
15411541
*/
15421542
staticint
15431543
timer_expired(structasync_ctx*actx)
15441544
{
1545-
#if defined(HAVE_SYS_EPOLL_H)
1546-
structitimerspecspec= {0};
1547-
1548-
if (timerfd_gettime(actx->timerfd,&spec)<0)
1549-
{
1550-
actx_error(actx,"getting timerfd value: %m");
1551-
return-1;
1552-
}
1553-
1554-
/*
1555-
* This implementation assumes we're using single-shot timers. If you
1556-
* change to using intervals, you'll need to reimplement this function
1557-
* too, possibly with the read() or select() interfaces for timerfd.
1558-
*/
1559-
Assert(spec.it_interval.tv_sec==0
1560-
&&spec.it_interval.tv_nsec==0);
1561-
1562-
/* If the remaining time to expiration is zero, we're done. */
1563-
return (spec.it_value.tv_sec==0
1564-
&&spec.it_value.tv_nsec==0);
1565-
#elif defined(HAVE_SYS_EVENT_H)
1545+
#if defined(HAVE_SYS_EPOLL_H)|| defined(HAVE_SYS_EVENT_H)
15661546
intres;
15671547

1568-
/* Is the timerqueueready? */
1548+
/* Is the timer ready? */
15691549
res=PQsocketPoll(actx->timerfd,1/* forRead */ ,0,0);
15701550
if (res<0)
15711551
{
1572-
actx_error(actx,"checkingkqueue for timeout: %m");
1552+
actx_error(actx,"checkingtimer expiration: %m");
15731553
return-1;
15741554
}
15751555

@@ -1601,6 +1581,36 @@ register_timer(CURLM *curlm, long timeout, void *ctx)
16011581
return0;
16021582
}
16031583

1584+
/*
1585+
* Removes any expired-timer event from the multiplexer. If was_expired is not
1586+
* NULL, it will contain whether or not the timer was expired at time of call.
1587+
*/
1588+
staticbool
1589+
drain_timer_events(structasync_ctx*actx,bool*was_expired)
1590+
{
1591+
intres;
1592+
1593+
res=timer_expired(actx);
1594+
if (res<0)
1595+
return false;
1596+
1597+
if (res>0)
1598+
{
1599+
/*
1600+
* Timer is expired. We could drain the event manually from the
1601+
* timerfd, but it's easier to simply disable it; that keeps the
1602+
* platform-specific code in set_timer().
1603+
*/
1604+
if (!set_timer(actx,-1))
1605+
return false;
1606+
}
1607+
1608+
if (was_expired)
1609+
*was_expired= (res>0);
1610+
1611+
return true;
1612+
}
1613+
16041614
/*
16051615
* Prints Curl request debugging information to stderr.
16061616
*
@@ -2804,6 +2814,22 @@ pg_fe_run_oauth_flow_impl(PGconn *conn)
28042814
{
28052815
PostgresPollingStatusTypestatus;
28062816

2817+
/*
2818+
* Clear any expired timeout before calling back into
2819+
* Curl. Curl is not guaranteed to do this for us, because
2820+
* its API expects us to use single-shot (i.e.
2821+
* edge-triggered) timeouts, and ours are level-triggered
2822+
* via the mux.
2823+
*
2824+
* This can't be combined with the comb_multiplexer() call
2825+
* below: we might accidentally clear a short timeout that
2826+
* was both set and expired during the call to
2827+
* drive_request().
2828+
*/
2829+
if (!drain_timer_events(actx,NULL))
2830+
gotoerror_return;
2831+
2832+
/* Move the request forward. */
28072833
status=drive_request(actx);
28082834

28092835
if (status==PGRES_POLLING_FAILED)
@@ -2826,24 +2852,26 @@ pg_fe_run_oauth_flow_impl(PGconn *conn)
28262852
}
28272853

28282854
caseOAUTH_STEP_WAIT_INTERVAL:
2829-
2830-
/*
2831-
* The client application is supposed to wait until our timer
2832-
* expires before calling PQconnectPoll() again, but that
2833-
* might not happen. To avoid sending a token request early,
2834-
* check the timer before continuing.
2835-
*/
2836-
if (!timer_expired(actx))
28372855
{
2838-
set_conn_altsock(conn,actx->timerfd);
2839-
returnPGRES_POLLING_READING;
2840-
}
2856+
boolexpired;
28412857

2842-
/* Disable the expired timer. */
2843-
if (!set_timer(actx,-1))
2844-
gotoerror_return;
2858+
/*
2859+
* The client application is supposed to wait until our
2860+
* timer expires before calling PQconnectPoll() again, but
2861+
* that might not happen. To avoid sending a token request
2862+
* early, check the timer before continuing.
2863+
*/
2864+
if (!drain_timer_events(actx,&expired))
2865+
gotoerror_return;
28452866

2846-
break;
2867+
if (!expired)
2868+
{
2869+
set_conn_altsock(conn,actx->timerfd);
2870+
returnPGRES_POLLING_READING;
2871+
}
2872+
2873+
break;
2874+
}
28472875
}
28482876

28492877
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp