Skip to content

Commit ef39adb

Browse files
committed
Merge branch 'PHP-8.1'
* PHP-8.1: Re-fix GH-8409: SSL handshake timeout persistent connections hanging Revert "Fix GH-8409: SSL handshake timeout persistent connections hanging"
2 parents b825756 + 14d7195 commit ef39adb

5 files changed

Lines changed: 52 additions & 61 deletions

File tree

‎Zend/zend.c‎

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,9 +1347,6 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
13471347
EG(num_errors)++;
13481348
EG(errors) = erealloc(EG(errors), sizeof(zend_error_info*) * EG(num_errors));
13491349
EG(errors)[EG(num_errors)-1] = info;
1350-
if (EG(record_errors_without_emitting)) {
1351-
return;
1352-
}
13531350
}
13541351

13551352
/* Report about uncaught exception in case of fatal errors */
@@ -1603,25 +1600,14 @@ ZEND_API ZEND_COLD void zend_error_zstr(int type, zend_string *message) {
16031600
zend_error_zstr_at(type, filename, lineno, message);
16041601
}
16051602

1606-
static zend_always_inline void zend_begin_record_errors_ex(bool no_emmitting)
1603+
ZEND_API void zend_begin_record_errors(void)
16071604
{
16081605
ZEND_ASSERT(!EG(record_errors) && "Error recording already enabled");
16091606
EG(record_errors) = true;
1610-
EG(record_errors_without_emitting) = no_emmitting;
16111607
EG(num_errors) = 0;
16121608
EG(errors) = NULL;
16131609
}
16141610

1615-
ZEND_API void zend_begin_record_errors(void)
1616-
{
1617-
zend_begin_record_errors_ex(false);
1618-
}
1619-
1620-
ZEND_API void zend_begin_record_errors_without_emitting(void)
1621-
{
1622-
zend_begin_record_errors_ex(true);
1623-
}
1624-
16251611
ZEND_API void zend_emit_recorded_errors(void)
16261612
{
16271613
EG(record_errors) = false;

‎Zend/zend.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,6 @@ ZEND_API void zend_save_error_handling(zend_error_handling *current);
398398
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current);
399399
ZEND_API void zend_restore_error_handling(zend_error_handling *saved);
400400
ZEND_API void zend_begin_record_errors(void);
401-
ZEND_API void zend_begin_record_errors_without_emitting(void);
402401
ZEND_API void zend_emit_recorded_errors(void);
403402
ZEND_API void zend_free_recorded_errors(void);
404403
END_EXTERN_C()

‎Zend/zend_globals.h‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,8 @@ struct _zend_executor_globals {
262262
zend_long fiber_stack_size;
263263

264264
/* If record_errors is enabled, all emitted diagnostics will be recorded,
265-
* in addition to being processed as usual unless record_errors_without_emitting
266-
* is enabled which supresses processing when the errors are recorded. */
265+
* in addition to being processed as usual. */
267266
bool record_errors;
268-
bool record_errors_without_emitting;
269267
uint32_t num_errors;
270268
zend_error_info **errors;
271269

‎ext/standard/tests/streams/gh8409.phpt‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,24 @@
22
GH-8409: Error in socket creation when error handler does not clean persistent connection
33
--FILE--
44
<?php
5-
set_error_handler(function($errno, $errstring, $errfile, $errline) {
5+
set_error_handler(function (int $errno, string $errstring): never {
6+
trigger_error($errstring, E_USER_ERROR);
7+
});
8+
9+
register_shutdown_function(function (): void {
610
foreach (get_resources() as $res) {
7-
if (get_resource_type($res) === "persistent stream") {
11+
if (get_resource_type($res) === 'persistent stream') {
812
echo "ERROR: persistent stream not closed\n";
13+
return;
914
}
1015
}
11-
echo "DONE\n";
12-
exit(1);
16+
echo "OK: persistent stream closed\n";
1317
});
1418

15-
stream_socket_client("tcp://9999.9999.9999.9999:9999", $error_code, $error_message, 0.2, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT);
19+
stream_socket_client('tcp://9999.9999.9999.9999:9999', $error_code, $error_message, 0.2, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT);
1620

1721
echo "ERROR: this should not be visible\n";
1822
?>
19-
--EXPECT--
20-
DONE
23+
--EXPECTF--
24+
Fatal error: stream_socket_client(): %s in %sgh8409.php on line %d
25+
OK: persistent stream closed

‎main/streams/transports.c‎

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
6161
php_stream_transport_factory factory = NULL;
6262
const char *p, *protocol = NULL;
6363
size_t n = 0;
64-
int failed = 0;
64+
bool failed = false;
65+
bool bailout = false;
6566
zend_string *error_text = NULL;
6667
struct timeval default_timeout = { 0, 0 };
6768

@@ -131,61 +132,63 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
131132
(char*)name, namelen, persistent_id, options, flags, timeout,
132133
context STREAMS_REL_CC);
133134

134-
zend_begin_record_errors_without_emitting();
135-
136135
if (stream) {
137-
php_stream_context_set(stream, context);
136+
zend_try {
137+
php_stream_context_set(stream, context);
138138

139-
if ((flags & STREAM_XPORT_SERVER) == 0) {
140-
/* client */
139+
if ((flags & STREAM_XPORT_SERVER) == 0) {
140+
/* client */
141141

142-
if (flags & (STREAM_XPORT_CONNECT|STREAM_XPORT_CONNECT_ASYNC)) {
143-
if (-1 == php_stream_xport_connect(stream, name, namelen,
144-
flags & STREAM_XPORT_CONNECT_ASYNC ? 1 : 0,
145-
timeout, &error_text, error_code)) {
142+
if (flags & (STREAM_XPORT_CONNECT|STREAM_XPORT_CONNECT_ASYNC)) {
143+
if (-1 == php_stream_xport_connect(stream, name, namelen,
144+
flags & STREAM_XPORT_CONNECT_ASYNC ? 1 : 0,
145+
timeout, &error_text, error_code)) {
146146

147-
ERR_RETURN(error_string, error_text, "connect() failed: %s");
147+
ERR_RETURN(error_string, error_text, "connect() failed: %s");
148148

149-
failed = 1;
150-
}
151-
}
152-
153-
} else {
154-
/* server */
155-
if (flags & STREAM_XPORT_BIND) {
156-
if (0 != php_stream_xport_bind(stream, name, namelen, &error_text)) {
157-
ERR_RETURN(error_string, error_text, "bind() failed: %s");
158-
failed = 1;
159-
} else if (flags & STREAM_XPORT_LISTEN) {
160-
zval *zbacklog = NULL;
161-
int backlog = 32;
162-
163-
if (PHP_STREAM_CONTEXT(stream) && (zbacklog = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "backlog")) != NULL) {
164-
backlog = zval_get_long(zbacklog);
149+
failed = true;
165150
}
151+
}
166152

167-
if (0 != php_stream_xport_listen(stream, backlog, &error_text)) {
168-
ERR_RETURN(error_string, error_text, "listen() failed: %s");
169-
failed = 1;
153+
} else {
154+
/* server */
155+
if (flags & STREAM_XPORT_BIND) {
156+
if (0 != php_stream_xport_bind(stream, name, namelen, &error_text)) {
157+
ERR_RETURN(error_string, error_text, "bind() failed: %s");
158+
failed = true;
159+
} else if (flags & STREAM_XPORT_LISTEN) {
160+
zval *zbacklog = NULL;
161+
int backlog = 32;
162+
163+
if (PHP_STREAM_CONTEXT(stream) && (zbacklog = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "socket", "backlog")) != NULL) {
164+
backlog = zval_get_long(zbacklog);
165+
}
166+
167+
if (0 != php_stream_xport_listen(stream, backlog, &error_text)) {
168+
ERR_RETURN(error_string, error_text, "listen() failed: %s");
169+
failed = true;
170+
}
170171
}
171172
}
172173
}
173-
}
174+
} zend_catch {
175+
bailout = true;
176+
} zend_end_try();
174177
}
175178

176-
if (failed) {
179+
if (failed || bailout) {
177180
/* failure means that they don't get a stream to play with */
178181
if (persistent_id) {
179182
php_stream_pclose(stream);
180183
} else {
181184
php_stream_close(stream);
182185
}
183186
stream = NULL;
187+
if (bailout) {
188+
zend_bailout();
189+
}
184190
}
185191

186-
zend_emit_recorded_errors();
187-
zend_free_recorded_errors();
188-
189192
return stream;
190193
}
191194

0 commit comments

Comments
 (0)