Skip to content

Commit 18f5808

Browse files
committed
Convert shmop resources to opaque objects
We make `shmop_close()` a NOP, and deprecate the function right away; detaching from SHM now happens when the wrapper object is freed.
1 parent 19d3e29 commit 18f5808

File tree

8 files changed

+112
-105
lines changed

8 files changed

+112
-105
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ PHP NEWS
151151
handlers). (bshaffer)
152152
. Fixed bug #73529 (session_decode() silently fails on wrong input). (cmb)
153153

154+
- Shmop:
155+
. Converted shmop resources to objects. (cmb)
156+
154157
- SimpleXML:
155158
. Fixed bug #75245 (Don't set content of elements with only whitespaces).
156159
(eriklundin)

UPGRADING

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,13 @@ PHP 8.0 UPGRADE NOTES
793793
- PGSQL / PDO PGSQL:
794794
. The PGSQL and PDO PGSQL extensions now require at least libpq 9.1.
795795

796+
- Shmop:
797+
. shmop_open() will now return a Shmop object rather than a resource. Return
798+
value checks using is_resource() should be replaced with checks for `false`.
799+
The shmop_close() function no longer has an effect, and is deprecated;
800+
instead the Shmop instance is automatically destroyed if it is no longer
801+
referenced.
802+
796803
========================================
797804
10. New Global Constants
798805
========================================

ext/shmop/php_shmop.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,6 @@ PHP_MINFO_FUNCTION(shmop);
3232
# include "win32/ipc.h"
3333
#endif
3434

35-
struct php_shmop
36-
{
37-
int shmid;
38-
key_t key;
39-
int shmflg;
40-
int shmatflg;
41-
char *addr;
42-
zend_long size;
43-
};
44-
45-
typedef struct {
46-
int le_shmop;
47-
} php_shmop_globals;
48-
49-
#ifdef ZTS
50-
#define SHMOPG(v) TSRMG(shmop_globals_id, php_shmop_globals *, v)
51-
#else
52-
#define SHMOPG(v) (shmop_globals.v)
53-
#endif
54-
5535
#else
5636

5737
#define phpext_shmop_ptr NULL

ext/shmop/shmop.c

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
#include "php.h"
2525
#include "php_ini.h"
26+
#include "Zend/zend_interfaces.h"
2627
#include "php_shmop.h"
2728
#include "shmop_arginfo.h"
2829

@@ -38,14 +39,6 @@
3839

3940
#include "ext/standard/info.h"
4041

41-
#ifdef ZTS
42-
int shmop_globals_id;
43-
#else
44-
php_shmop_globals shmop_globals;
45-
#endif
46-
47-
int shm_type;
48-
4942
/* {{{ shmop_module_entry
5043
*/
5144
zend_module_entry shmop_module_entry = {
@@ -66,22 +59,70 @@ zend_module_entry shmop_module_entry = {
6659
ZEND_GET_MODULE(shmop)
6760
#endif
6861

69-
/* {{{ rsclean
70-
*/
71-
static void rsclean(zend_resource *rsrc)
62+
typedef struct php_shmop
63+
{
64+
int shmid;
65+
key_t key;
66+
int shmflg;
67+
int shmatflg;
68+
char *addr;
69+
zend_long size;
70+
zend_object std;
71+
} php_shmop;
72+
73+
zend_class_entry *shmop_ce;
74+
static zend_object_handlers shmop_object_handlers;
75+
76+
static inline php_shmop *shmop_from_obj(zend_object *obj)
77+
{
78+
return (php_shmop *)((char *)(obj) - XtOffsetOf(php_shmop, std));
79+
}
80+
81+
#define Z_SHMOP_P(zv) shmop_from_obj(Z_OBJ_P(zv))
82+
83+
static zend_object *shmop_create_object(zend_class_entry *class_type)
84+
{
85+
php_shmop *intern = zend_object_alloc(sizeof(php_shmop), class_type);
86+
87+
zend_object_std_init(&intern->std, class_type);
88+
object_properties_init(&intern->std, class_type);
89+
intern->std.handlers = &shmop_object_handlers;
90+
91+
return &intern->std;
92+
}
93+
94+
static zend_function *shmop_get_constructor(zend_object *object)
95+
{
96+
zend_throw_error(NULL, "Cannot directly construct Shmop, use shmop_open() instead");
97+
return NULL;
98+
}
99+
100+
static void shmop_free_obj(zend_object *object)
72101
{
73-
struct php_shmop *shmop = (struct php_shmop *)rsrc->ptr;
102+
php_shmop *shmop = shmop_from_obj(object);
74103

75104
shmdt(shmop->addr);
76-
efree(shmop);
105+
106+
zend_object_std_dtor(&shmop->std);
77107
}
78-
/* }}} */
79108

80109
/* {{{ PHP_MINIT_FUNCTION
81110
*/
82111
PHP_MINIT_FUNCTION(shmop)
83112
{
84-
shm_type = zend_register_list_destructors_ex(rsclean, NULL, "shmop", module_number);
113+
zend_class_entry ce;
114+
INIT_CLASS_ENTRY(ce, "Shmop", class_Shmop_methods);
115+
shmop_ce = zend_register_internal_class(&ce);
116+
shmop_ce->ce_flags |= ZEND_ACC_FINAL;
117+
shmop_ce->create_object = shmop_create_object;
118+
shmop_ce->serialize = zend_class_serialize_deny;
119+
shmop_ce->unserialize = zend_class_unserialize_deny;
120+
121+
memcpy(&shmop_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
122+
shmop_object_handlers.offset = XtOffsetOf(php_shmop, std);
123+
shmop_object_handlers.free_obj = shmop_free_obj;
124+
shmop_object_handlers.get_constructor = shmop_get_constructor;
125+
shmop_object_handlers.clone_obj = NULL;
85126

86127
return SUCCESS;
87128
}
@@ -97,12 +138,12 @@ PHP_MINFO_FUNCTION(shmop)
97138
}
98139
/* }}} */
99140

100-
/* {{{ proto resource shmop_open(int key, string flags, int mode, int size)
141+
/* {{{ proto Shmop shmop_open(int key, string flags, int mode, int size)
101142
gets and attaches a shared memory segment */
102143
PHP_FUNCTION(shmop_open)
103144
{
104145
zend_long key, mode, size;
105-
struct php_shmop *shmop;
146+
php_shmop *shmop;
106147
struct shmid_ds shm;
107148
char *flags;
108149
size_t flags_len;
@@ -116,9 +157,8 @@ PHP_FUNCTION(shmop_open)
116157
RETURN_FALSE;
117158
}
118159

119-
shmop = emalloc(sizeof(struct php_shmop));
120-
memset(shmop, 0, sizeof(struct php_shmop));
121-
160+
object_init_ex(return_value, shmop_ce);
161+
shmop = Z_SHMOP_P(return_value);
122162
shmop->key = key;
123163
shmop->shmflg |= mode;
124164

@@ -175,32 +215,30 @@ PHP_FUNCTION(shmop_open)
175215
}
176216

177217
shmop->size = shm.shm_segsz;
218+
return;
178219

179-
RETURN_RES(zend_register_resource(shmop, shm_type));
180220
err:
181-
efree(shmop);
221+
zend_object_release(Z_OBJ_P(return_value));
182222
RETURN_FALSE;
183223
}
184224
/* }}} */
185225

186-
/* {{{ proto string shmop_read(resource shmid, int start, int count)
226+
/* {{{ proto string shmop_read(Shmop shmid, int start, int count)
187227
reads from a shm segment */
188228
PHP_FUNCTION(shmop_read)
189229
{
190230
zval *shmid;
191231
zend_long start, count;
192-
struct php_shmop *shmop;
232+
php_shmop *shmop;
193233
char *startaddr;
194234
int bytes;
195235
zend_string *return_string;
196236

197-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &shmid, &start, &count) == FAILURE) {
237+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oll", &shmid, shmop_ce, &start, &count) == FAILURE) {
198238
RETURN_THROWS();
199239
}
200240

201-
if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
202-
RETURN_THROWS();
203-
}
241+
shmop = Z_SHMOP_P(shmid);
204242

205243
if (start < 0 || start > shmop->size) {
206244
php_error_docref(NULL, E_WARNING, "Start is out of range");
@@ -221,62 +259,50 @@ PHP_FUNCTION(shmop_read)
221259
}
222260
/* }}} */
223261

224-
/* {{{ proto void shmop_close(resource shmid)
225-
closes a shared memory segment */
262+
/* {{{ proto void shmop_close(Shmop shmid)
263+
used to close a shared memory segment; now a NOP */
226264
PHP_FUNCTION(shmop_close)
227265
{
228266
zval *shmid;
229-
struct php_shmop *shmop;
230267

231-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
268+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
232269
RETURN_THROWS();
233270
}
234-
235-
236-
if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
237-
RETURN_THROWS();
238-
}
239-
240-
zend_list_close(Z_RES_P(shmid));
241271
}
242272
/* }}} */
243273

244-
/* {{{ proto int shmop_size(resource shmid)
274+
/* {{{ proto int shmop_size(Shmop shmid)
245275
returns the shm size */
246276
PHP_FUNCTION(shmop_size)
247277
{
248278
zval *shmid;
249-
struct php_shmop *shmop;
279+
php_shmop *shmop;
250280

251-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
281+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
252282
RETURN_THROWS();
253283
}
254284

255-
if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
256-
RETURN_THROWS();
257-
}
285+
shmop = Z_SHMOP_P(shmid);
258286

259287
RETURN_LONG(shmop->size);
260288
}
261289
/* }}} */
262290

263-
/* {{{ proto int shmop_write(resource shmid, string data, int offset)
291+
/* {{{ proto int shmop_write(Shmop shmid, string data, int offset)
264292
writes to a shared memory segment */
265293
PHP_FUNCTION(shmop_write)
266294
{
267-
struct php_shmop *shmop;
295+
php_shmop *shmop;
268296
zend_long writesize;
269297
zend_long offset;
270298
zend_string *data;
271299
zval *shmid;
272300

273-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rSl", &shmid, &data, &offset) == FAILURE) {
301+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &shmid, shmop_ce, &data, &offset) == FAILURE) {
274302
RETURN_THROWS();
275303
}
276304

277-
if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
278-
RETURN_THROWS();
279-
}
305+
shmop = Z_SHMOP_P(shmid);
280306

281307
if ((shmop->shmatflg & SHM_RDONLY) == SHM_RDONLY) {
282308
php_error_docref(NULL, E_WARNING, "Trying to write to a read only segment");
@@ -295,20 +321,18 @@ PHP_FUNCTION(shmop_write)
295321
}
296322
/* }}} */
297323

298-
/* {{{ proto bool shmop_delete(resource shmid)
324+
/* {{{ proto bool shmop_delete(Shmop shmid)
299325
mark segment for deletion */
300326
PHP_FUNCTION(shmop_delete)
301327
{
302328
zval *shmid;
303-
struct php_shmop *shmop;
329+
php_shmop *shmop;
304330

305-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
331+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
306332
RETURN_THROWS();
307333
}
308334

309-
if ((shmop = (struct php_shmop *)zend_fetch_resource(Z_RES_P(shmid), "shmop", shm_type)) == NULL) {
310-
RETURN_THROWS();
311-
}
335+
shmop = Z_SHMOP_P(shmid);
312336

313337
if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
314338
php_error_docref(NULL, E_WARNING, "Can't mark segment for deletion (are you the owner?)");

ext/shmop/shmop.stub.php

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,17 @@
22

33
/** @generate-function-entries */
44

5-
/** @return resource|false */
6-
function shmop_open(int $key, string $flags, int $mode, int $size) {}
5+
final class Shmop {}
76

8-
/** @param resource $shmid */
9-
function shmop_read($shmid, int $start, int $count): string|false {}
7+
function shmop_open(int $key, string $flags, int $mode, int $size): Shmop|false {}
108

11-
/** @param resource $shmid */
12-
function shmop_close($shmid): void {}
9+
function shmop_read(Shmop $shmid, int $start, int $count): string|false {}
1310

14-
/** @param resource $shmid */
15-
function shmop_size($shmid): int {}
11+
/** @deprecated */
12+
function shmop_close(Shmop $shmid): void {}
1613

17-
/** @param resource $shmid */
18-
function shmop_write($shmid, string $data, int $offset): int|false {}
14+
function shmop_size(Shmop $shmid): int {}
1915

20-
/** @param resource $shmid */
21-
function shmop_delete($shmid): bool {}
16+
function shmop_write(Shmop $shmid, string $data, int $offset): int|false {}
17+
18+
function shmop_delete(Shmop $shmid): bool {}

0 commit comments

Comments
 (0)