Skip to content

Commit d052742

Browse files
committed
Fix GH-8409: SSL handshake timeout persistent connections hanging
This is not actually related to SSL handshake but stream socket creation which does not clean errors if the error handler is set. This fix prevents emitting errors until the stream is freed.
1 parent 71c22ef commit d052742

File tree

7 files changed

+58
-9
lines changed

7 files changed

+58
-9
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ PHP NEWS
4949
- Streams:
5050
. Fixed bug GH-8472 (The resource returned by stream_socket_accept may have
5151
incorrect metadata). (Jakub Zelenka)
52+
. Fixed bug GH-8409 (SSL handshake timeout leaves persistent connections
53+
hanging). (Jakub Zelenka)
5254

5355
04 Aug 2022, PHP 8.1.9
5456

Zend/zend.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,9 @@ ZEND_API ZEND_COLD void zend_error_zstr_at(
13661366
EG(num_errors)++;
13671367
EG(errors) = erealloc(EG(errors), sizeof(zend_error_info) * EG(num_errors));
13681368
EG(errors)[EG(num_errors)-1] = info;
1369+
if (EG(record_errors_without_emitting)) {
1370+
return;
1371+
}
13691372
}
13701373

13711374
/* Report about uncaught exception in case of fatal errors */
@@ -1619,14 +1622,34 @@ ZEND_API ZEND_COLD void zend_error_zstr(int type, zend_string *message) {
16191622
zend_error_zstr_at(type, filename, lineno, message);
16201623
}
16211624

1622-
ZEND_API void zend_begin_record_errors(void)
1625+
static zend_always_inline void zend_begin_record_errors_ex(bool no_emmitting)
16231626
{
1624-
ZEND_ASSERT(!EG(record_errors) && "Error recoreding already enabled");
1627+
ZEND_ASSERT(!EG(record_errors) && "Error recording already enabled");
16251628
EG(record_errors) = true;
1629+
EG(record_errors_without_emitting) = no_emmitting;
16261630
EG(num_errors) = 0;
16271631
EG(errors) = NULL;
16281632
}
16291633

1634+
ZEND_API void zend_begin_record_errors(void)
1635+
{
1636+
zend_begin_record_errors_ex(false);
1637+
}
1638+
1639+
ZEND_API void zend_begin_record_errors_without_emitting(void)
1640+
{
1641+
zend_begin_record_errors_ex(true);
1642+
}
1643+
1644+
ZEND_API void zend_emit_recorded_errors(void)
1645+
{
1646+
EG(record_errors) = false;
1647+
for (uint32_t i = 0; i < EG(num_errors); i++) {
1648+
zend_error_info *error = EG(errors)[i];
1649+
zend_error_zstr_at(error->type, error->filename, error->lineno, error->message);
1650+
}
1651+
}
1652+
16301653
ZEND_API void zend_free_recorded_errors(void)
16311654
{
16321655
if (!EG(num_errors)) {

Zend/zend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,8 @@ ZEND_API void zend_save_error_handling(zend_error_handling *current);
394394
ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current);
395395
ZEND_API void zend_restore_error_handling(zend_error_handling *saved);
396396
ZEND_API void zend_begin_record_errors(void);
397+
ZEND_API void zend_begin_record_errors_without_emitting(void);
398+
ZEND_API void zend_emit_recorded_errors(void);
397399
ZEND_API void zend_free_recorded_errors(void);
398400
END_EXTERN_C()
399401

Zend/zend_globals.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,10 @@ struct _zend_executor_globals {
261261
zend_long fiber_stack_size;
262262

263263
/* If record_errors is enabled, all emitted diagnostics will be recorded,
264-
* in addition to being processed as usual. */
264+
* in addition to being processed as usual unless record_errors_without_emitting
265+
* is enabled which supresses processing when the errors are recorded. */
265266
bool record_errors;
267+
bool record_errors_without_emitting;
266268
uint32_t num_errors;
267269
zend_error_info **errors;
268270

ext/opcache/ZendAccelerator.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3929,12 +3929,7 @@ static void preload_link(void)
39293929

39303930
/* Inheritance successful, print out any warnings. */
39313931
zend_error_cb = orig_error_cb;
3932-
EG(record_errors) = false;
3933-
for (uint32_t i = 0; i < EG(num_errors); i++) {
3934-
zend_error_info *error = EG(errors)[i];
3935-
zend_error_zstr_at(
3936-
error->type, error->filename, error->lineno, error->message);
3937-
}
3932+
zend_emit_recorded_errors();
39383933
} zend_catch {
39393934
/* Clear variance obligations that were left behind on bailout. */
39403935
if (CG(delayed_variance_obligations)) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-8409: Error in socket creation when error handler does not clean persistent connection
3+
--FILE--
4+
<?php
5+
set_error_handler(function($errno, $errstring, $errfile, $errline) {
6+
foreach (get_resources() as $res) {
7+
if (get_resource_type($res) === "persistent stream") {
8+
echo "ERROR: persistent stream not closed\n";
9+
}
10+
}
11+
echo "DONE\n";
12+
exit(1);
13+
});
14+
15+
stream_socket_client("tcp://9999.9999.9999.9999:9999", $error_code, $error_message, 0.2, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT);
16+
17+
echo "ERROR: this should not be visible\n";
18+
?>
19+
--EXPECT--
20+
DONE

main/streams/transports.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
131131
(char*)name, namelen, persistent_id, options, flags, timeout,
132132
context STREAMS_REL_CC);
133133

134+
zend_begin_record_errors_without_emitting();
135+
134136
if (stream) {
135137
php_stream_context_set(stream, context);
136138

@@ -181,6 +183,9 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in
181183
stream = NULL;
182184
}
183185

186+
zend_emit_recorded_errors();
187+
zend_free_recorded_errors();
188+
184189
return stream;
185190
}
186191

0 commit comments

Comments
 (0)