mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
ext/pgsql: adding pg_socket_poll.
Using PQSocketPoll to poll on a connection's socket. Returns immediatly is there no event expected on read and write. Other than that, it is a thin wrapper on top of poll, thus reflecting its return value. close GH-14366
This commit is contained in:
1
NEWS
1
NEWS
@@ -197,6 +197,7 @@ PHP NEWS
|
||||
. Added pg_change_password to alter an user's password. (David Carlier)
|
||||
. Added pg_put_copy_data/pg_put_copy_end to send COPY commands and signal
|
||||
the end of the COPY. (David Carlier)
|
||||
. Added pg_socket_poll to poll on the connection. (David Carlier)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug GH-12532 (PharData created from zip has incorrect timestamp).
|
||||
|
||||
@@ -549,6 +549,8 @@ PHP 8.4 UPGRADE NOTES
|
||||
transparently the password encryption from the database settings.
|
||||
. Added pg_put_copy_data to send COPY commands and pg_put_copy_end to send
|
||||
end-of-data to the server.
|
||||
. Added pg_socket_poll to check if there is any read and/or write events
|
||||
with an optional timeout.
|
||||
|
||||
- Sodium:
|
||||
. Added the sodium_crypto_aead_aegis128l_*() and sodium_crypto_aead_aegis256l_*()
|
||||
|
||||
@@ -68,6 +68,7 @@ if test "$PHP_PGSQL" != "no"; then
|
||||
AC_CHECK_LIB(pq, PQsetErrorContextVisibility, AC_DEFINE(HAVE_PG_CONTEXT_VISIBILITY,1,[PostgreSQL 9.6 or later]))
|
||||
AC_CHECK_LIB(pq, PQresultMemorySize, AC_DEFINE(HAVE_PG_RESULT_MEMORY_SIZE,1,[PostgreSQL 12 or later]))
|
||||
AC_CHECK_LIB(pq, PQchangePassword, AC_DEFINE(HAVE_PG_CHANGE_PASSWORD,1,[PostgreSQL 17 or later]))
|
||||
AC_CHECK_LIB(pq, PQsocketPoll, AC_DEFINE(HAVE_PG_SOCKET_POLL,1,[PostgreSQL 17 or later]))
|
||||
LIBS=$old_LIBS
|
||||
LDFLAGS=$old_LDFLAGS
|
||||
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
#include "php_globals.h"
|
||||
#include "zend_exceptions.h"
|
||||
#include "zend_attributes.h"
|
||||
#if !defined(HAVE_PG_SOCKET_POLL)
|
||||
#include "php_network.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PGSQL
|
||||
|
||||
@@ -443,6 +446,41 @@ static PGresult *PQchangePassword(PGconn *conn, const char *user, const char *pa
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_PG_SOCKET_POLL)
|
||||
static int PQsocketPoll(int socket, int read, int write, time_t timeout)
|
||||
{
|
||||
if (!read && !write)
|
||||
return 0;
|
||||
|
||||
php_pollfd fd;
|
||||
int ts = -1;
|
||||
|
||||
fd.fd = socket;
|
||||
fd.events = POLLERR;
|
||||
fd.revents = 0;
|
||||
|
||||
if (read) {
|
||||
fd.events |= POLLIN;
|
||||
}
|
||||
|
||||
if (write) {
|
||||
fd.events |= POLLOUT;
|
||||
}
|
||||
|
||||
if (timeout != (time_t)ts) {
|
||||
time_t cur = time(NULL);
|
||||
|
||||
if (timeout > cur) {
|
||||
ts = (timeout - cur) * 1000;
|
||||
} else {
|
||||
ts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return php_poll2(&fd, 1, ts);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* {{{ PHP_INI */
|
||||
PHP_INI_BEGIN()
|
||||
STD_PHP_INI_BOOLEAN( "pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_pgsql_globals, pgsql_globals)
|
||||
@@ -6165,3 +6203,29 @@ PHP_FUNCTION(pg_put_copy_end)
|
||||
|
||||
RETURN_LONG((zend_long)PQputCopyEnd(link->conn, err));
|
||||
}
|
||||
|
||||
PHP_FUNCTION(pg_socket_poll)
|
||||
{
|
||||
zval *z_socket;
|
||||
php_stream *stream;
|
||||
php_socket_t socket;
|
||||
zend_long read, write;
|
||||
zend_long ts = -1;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(3, 4)
|
||||
Z_PARAM_RESOURCE(z_socket)
|
||||
Z_PARAM_LONG(read)
|
||||
Z_PARAM_LONG(write)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(ts)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
php_stream_from_zval(stream, z_socket);
|
||||
|
||||
if (php_stream_cast(stream, PHP_STREAM_AS_SOCKETD, (void **)&socket, 0)) {
|
||||
zend_argument_type_error(1, "invalid resource socket");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
RETURN_LONG((zend_long)PQsocketPoll(socket, (int)read, (int)write, (int)ts));
|
||||
}
|
||||
|
||||
@@ -952,6 +952,11 @@ namespace {
|
||||
|
||||
function pg_put_copy_data(PgSql\Connection $connection, string $cmd): int {}
|
||||
function pg_put_copy_end(PgSql\Connection $connection, ?string $error = null): int {}
|
||||
|
||||
/**
|
||||
* @param resource $socket
|
||||
*/
|
||||
function pg_socket_poll($socket, int $read, int $write, int $timeout = -1): int {}
|
||||
}
|
||||
|
||||
namespace PgSql {
|
||||
|
||||
11
ext/pgsql/pgsql_arginfo.h
generated
11
ext/pgsql/pgsql_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: edc626b255224ed76333223c90cfab062415637f */
|
||||
* Stub hash: 4a2a5778003aa741952e16617e5bdb2ad06e6e16 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0)
|
||||
@@ -481,6 +481,13 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_put_copy_end, 0, 1, IS_LONG,
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, error, IS_STRING, 1, "null")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_socket_poll, 0, 3, IS_LONG, 0)
|
||||
ZEND_ARG_INFO(0, socket)
|
||||
ZEND_ARG_TYPE_INFO(0, read, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, write, IS_LONG, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_LONG, 0, "-1")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_FUNCTION(pg_connect);
|
||||
ZEND_FUNCTION(pg_pconnect);
|
||||
ZEND_FUNCTION(pg_connect_poll);
|
||||
@@ -581,6 +588,7 @@ ZEND_FUNCTION(pg_result_memory_size);
|
||||
ZEND_FUNCTION(pg_change_password);
|
||||
ZEND_FUNCTION(pg_put_copy_data);
|
||||
ZEND_FUNCTION(pg_put_copy_end);
|
||||
ZEND_FUNCTION(pg_socket_poll);
|
||||
|
||||
static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(pg_connect, arginfo_pg_connect)
|
||||
@@ -706,6 +714,7 @@ static const zend_function_entry ext_functions[] = {
|
||||
ZEND_FE(pg_change_password, arginfo_pg_change_password)
|
||||
ZEND_FE(pg_put_copy_data, arginfo_pg_put_copy_data)
|
||||
ZEND_FE(pg_put_copy_end, arginfo_pg_put_copy_end)
|
||||
ZEND_FE(pg_socket_poll, arginfo_pg_socket_poll)
|
||||
ZEND_FE_END
|
||||
};
|
||||
|
||||
|
||||
49
ext/pgsql/tests/pg_socket_poll.phpt
Normal file
49
ext/pgsql/tests/pg_socket_poll.phpt
Normal file
@@ -0,0 +1,49 @@
|
||||
--TEST--
|
||||
PostgreSQL poll on connection's socket
|
||||
--EXTENSIONS--
|
||||
pgsql
|
||||
--SKIPIF--
|
||||
<?php
|
||||
include("inc/skipif.inc");
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
include('inc/config.inc');
|
||||
include('inc/nonblocking.inc');
|
||||
|
||||
if (!($db = pg_connect($conn_str, PGSQL_CONNECT_ASYNC))) die("pg_connect failed");
|
||||
$socket = pg_socket($db);
|
||||
$fp = fopen(__DIR__ . "/inc/config.inc", "r");
|
||||
try {
|
||||
pg_socket_poll($fp, 0, 0);
|
||||
} catch (\TypeError $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
if (($topoll = pg_socket_poll($socket, 1, 1, 1)) === -1) die("pg_socket_poll failed");
|
||||
stream_set_blocking($socket, false);
|
||||
|
||||
while (1) {
|
||||
switch ($status = pg_connect_poll($db)) {
|
||||
case PGSQL_POLLING_READING:
|
||||
nb_is_writable($socket);
|
||||
break;
|
||||
case PGSQL_POLLING_WRITING:
|
||||
nb_is_writable($socket);
|
||||
break;
|
||||
case PGSQL_POLLING_OK:
|
||||
break 2;
|
||||
default:
|
||||
die("poll failed");
|
||||
}
|
||||
}
|
||||
assert(pg_connection_status($db) === PGSQL_CONNECTION_OK);
|
||||
echo "OK";
|
||||
|
||||
pg_close($db);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
pg_socket_poll(): Argument #1 ($socket) invalid resource socket
|
||||
OK
|
||||
Reference in New Issue
Block a user