Skip to content

Commit 768f08e

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 dd9d0a9 commit 768f08e

File tree

6 files changed

+94
-97
lines changed

6 files changed

+94
-97
lines changed

ext/shmop/php_shmop.h

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

35-
struct php_shmop
35+
typedef struct php_shmop
3636
{
3737
int shmid;
3838
key_t key;
3939
int shmflg;
4040
int shmatflg;
4141
char *addr;
4242
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
43+
zend_object std;
44+
} php_shmop;
5445

5546
#else
5647

ext/shmop/shmop.c

Lines changed: 70 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,59 @@ 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+
zend_class_entry *shmop_ce;
63+
static zend_object_handlers shmop_object_handlers;
64+
65+
static inline php_shmop *shmop_from_obj(zend_object *obj)
66+
{
67+
return (php_shmop *)((char *)(obj) - XtOffsetOf(php_shmop, std));
68+
}
69+
70+
#define Z_SHMOP_P(zv) shmop_from_obj(Z_OBJ_P(zv))
71+
72+
static zend_object *shmop_create_object(zend_class_entry *class_type)
73+
{
74+
php_shmop *intern = zend_object_alloc(sizeof(php_shmop), class_type);
75+
76+
zend_object_std_init(&intern->std, class_type);
77+
object_properties_init(&intern->std, class_type);
78+
intern->std.handlers = &shmop_object_handlers;
79+
80+
return &intern->std;
81+
}
82+
83+
static zend_function *shmop_get_constructor(zend_object *object)
84+
{
85+
zend_throw_error(NULL, "Cannot directly construct Shmop, use shmop_open() instead");
86+
return NULL;
87+
}
88+
89+
static void shmop_free_obj(zend_object *object)
7290
{
73-
struct php_shmop *shmop = (struct php_shmop *)rsrc->ptr;
91+
php_shmop *shmop = shmop_from_obj(object);
7492

7593
shmdt(shmop->addr);
76-
efree(shmop);
94+
95+
zend_object_std_dtor(&shmop->std);
7796
}
78-
/* }}} */
7997

8098
/* {{{ PHP_MINIT_FUNCTION
8199
*/
82100
PHP_MINIT_FUNCTION(shmop)
83101
{
84-
shm_type = zend_register_list_destructors_ex(rsclean, NULL, "shmop", module_number);
102+
zend_class_entry ce;
103+
INIT_CLASS_ENTRY(ce, "Shmop", class_Shmop_methods);
104+
shmop_ce = zend_register_internal_class(&ce);
105+
shmop_ce->ce_flags |= ZEND_ACC_FINAL;
106+
shmop_ce->create_object = shmop_create_object;
107+
shmop_ce->serialize = zend_class_serialize_deny;
108+
shmop_ce->unserialize = zend_class_unserialize_deny;
109+
110+
memcpy(&shmop_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
111+
shmop_object_handlers.offset = XtOffsetOf(php_shmop, std);
112+
shmop_object_handlers.free_obj = shmop_free_obj;
113+
shmop_object_handlers.get_constructor = shmop_get_constructor;
114+
shmop_object_handlers.clone_obj = NULL;
85115

86116
return SUCCESS;
87117
}
@@ -97,12 +127,12 @@ PHP_MINFO_FUNCTION(shmop)
97127
}
98128
/* }}} */
99129

100-
/* {{{ proto resource shmop_open(int key, string flags, int mode, int size)
130+
/* {{{ proto Shmop shmop_open(int key, string flags, int mode, int size)
101131
gets and attaches a shared memory segment */
102132
PHP_FUNCTION(shmop_open)
103133
{
104134
zend_long key, mode, size;
105-
struct php_shmop *shmop;
135+
php_shmop *shmop;
106136
struct shmid_ds shm;
107137
char *flags;
108138
size_t flags_len;
@@ -116,9 +146,8 @@ PHP_FUNCTION(shmop_open)
116146
RETURN_FALSE;
117147
}
118148

119-
shmop = emalloc(sizeof(struct php_shmop));
120-
memset(shmop, 0, sizeof(struct php_shmop));
121-
149+
object_init_ex(return_value, shmop_ce);
150+
shmop = Z_SHMOP_P(return_value);
122151
shmop->key = key;
123152
shmop->shmflg |= mode;
124153

@@ -175,32 +204,30 @@ PHP_FUNCTION(shmop_open)
175204
}
176205

177206
shmop->size = shm.shm_segsz;
207+
return;
178208

179-
RETURN_RES(zend_register_resource(shmop, shm_type));
180209
err:
181-
efree(shmop);
210+
zend_object_release(Z_OBJ_P(return_value));
182211
RETURN_FALSE;
183212
}
184213
/* }}} */
185214

186-
/* {{{ proto string shmop_read(resource shmid, int start, int count)
215+
/* {{{ proto string shmop_read(Shmop shmid, int start, int count)
187216
reads from a shm segment */
188217
PHP_FUNCTION(shmop_read)
189218
{
190219
zval *shmid;
191220
zend_long start, count;
192-
struct php_shmop *shmop;
221+
php_shmop *shmop;
193222
char *startaddr;
194223
int bytes;
195224
zend_string *return_string;
196225

197-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &shmid, &start, &count) == FAILURE) {
226+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oll", &shmid, shmop_ce, &start, &count) == FAILURE) {
198227
RETURN_THROWS();
199228
}
200229

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

205232
if (start < 0 || start > shmop->size) {
206233
php_error_docref(NULL, E_WARNING, "Start is out of range");
@@ -221,62 +248,50 @@ PHP_FUNCTION(shmop_read)
221248
}
222249
/* }}} */
223250

224-
/* {{{ proto void shmop_close(resource shmid)
225-
closes a shared memory segment */
251+
/* {{{ proto void shmop_close(Shmop shmid)
252+
used to close a shared memory segment; now a NOP */
226253
PHP_FUNCTION(shmop_close)
227254
{
228255
zval *shmid;
229-
struct php_shmop *shmop;
230256

231-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
257+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
232258
RETURN_THROWS();
233259
}
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));
241260
}
242261
/* }}} */
243262

244-
/* {{{ proto int shmop_size(resource shmid)
263+
/* {{{ proto int shmop_size(Shmop shmid)
245264
returns the shm size */
246265
PHP_FUNCTION(shmop_size)
247266
{
248267
zval *shmid;
249-
struct php_shmop *shmop;
268+
php_shmop *shmop;
250269

251-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
270+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
252271
RETURN_THROWS();
253272
}
254273

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

259276
RETURN_LONG(shmop->size);
260277
}
261278
/* }}} */
262279

263-
/* {{{ proto int shmop_write(resource shmid, string data, int offset)
280+
/* {{{ proto int shmop_write(Shmop shmid, string data, int offset)
264281
writes to a shared memory segment */
265282
PHP_FUNCTION(shmop_write)
266283
{
267-
struct php_shmop *shmop;
284+
php_shmop *shmop;
268285
zend_long writesize;
269286
zend_long offset;
270287
zend_string *data;
271288
zval *shmid;
272289

273-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rSl", &shmid, &data, &offset) == FAILURE) {
290+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &shmid, shmop_ce, &data, &offset) == FAILURE) {
274291
RETURN_THROWS();
275292
}
276293

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

281296
if ((shmop->shmatflg & SHM_RDONLY) == SHM_RDONLY) {
282297
php_error_docref(NULL, E_WARNING, "Trying to write to a read only segment");
@@ -295,20 +310,18 @@ PHP_FUNCTION(shmop_write)
295310
}
296311
/* }}} */
297312

298-
/* {{{ proto bool shmop_delete(resource shmid)
313+
/* {{{ proto bool shmop_delete(Shmop shmid)
299314
mark segment for deletion */
300315
PHP_FUNCTION(shmop_delete)
301316
{
302317
zval *shmid;
303-
struct php_shmop *shmop;
318+
php_shmop *shmop;
304319

305-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &shmid) == FAILURE) {
320+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &shmid, shmop_ce) == FAILURE) {
306321
RETURN_THROWS();
307322
}
308323

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

313326
if (shmctl(shmop->shmid, IPC_RMID, NULL)) {
314327
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 {}

ext/shmop/shmop_arginfo.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
/* This is a generated file, edit the .stub.php file instead. */
22

3-
ZEND_BEGIN_ARG_INFO_EX(arginfo_shmop_open, 0, 0, 4)
3+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_shmop_open, 0, 4, Shmop, MAY_BE_FALSE)
44
ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0)
55
ZEND_ARG_TYPE_INFO(0, flags, IS_STRING, 0)
66
ZEND_ARG_TYPE_INFO(0, mode, IS_LONG, 0)
77
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
88
ZEND_END_ARG_INFO()
99

1010
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_shmop_read, 0, 3, MAY_BE_STRING|MAY_BE_FALSE)
11-
ZEND_ARG_INFO(0, shmid)
11+
ZEND_ARG_OBJ_INFO(0, shmid, Shmop, 0)
1212
ZEND_ARG_TYPE_INFO(0, start, IS_LONG, 0)
1313
ZEND_ARG_TYPE_INFO(0, count, IS_LONG, 0)
1414
ZEND_END_ARG_INFO()
1515

1616
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shmop_close, 0, 1, IS_VOID, 0)
17-
ZEND_ARG_INFO(0, shmid)
17+
ZEND_ARG_OBJ_INFO(0, shmid, Shmop, 0)
1818
ZEND_END_ARG_INFO()
1919

2020
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shmop_size, 0, 1, IS_LONG, 0)
21-
ZEND_ARG_INFO(0, shmid)
21+
ZEND_ARG_OBJ_INFO(0, shmid, Shmop, 0)
2222
ZEND_END_ARG_INFO()
2323

2424
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_shmop_write, 0, 3, MAY_BE_LONG|MAY_BE_FALSE)
25-
ZEND_ARG_INFO(0, shmid)
25+
ZEND_ARG_OBJ_INFO(0, shmid, Shmop, 0)
2626
ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
2727
ZEND_ARG_TYPE_INFO(0, offset, IS_LONG, 0)
2828
ZEND_END_ARG_INFO()
2929

3030
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_shmop_delete, 0, 1, _IS_BOOL, 0)
31-
ZEND_ARG_INFO(0, shmid)
31+
ZEND_ARG_OBJ_INFO(0, shmid, Shmop, 0)
3232
ZEND_END_ARG_INFO()
3333

3434

@@ -43,9 +43,14 @@ ZEND_FUNCTION(shmop_delete);
4343
static const zend_function_entry ext_functions[] = {
4444
ZEND_FE(shmop_open, arginfo_shmop_open)
4545
ZEND_FE(shmop_read, arginfo_shmop_read)
46-
ZEND_FE(shmop_close, arginfo_shmop_close)
46+
ZEND_DEP_FE(shmop_close, arginfo_shmop_close)
4747
ZEND_FE(shmop_size, arginfo_shmop_size)
4848
ZEND_FE(shmop_write, arginfo_shmop_write)
4949
ZEND_FE(shmop_delete, arginfo_shmop_delete)
5050
ZEND_FE_END
5151
};
52+
53+
54+
static const zend_function_entry class_Shmop_methods[] = {
55+
ZEND_FE_END
56+
};

ext/shmop/tests/001.phpt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ shmop extension test
3232

3333
echo "data in memory is: " . shmop_read($shm_id, 0, $written) . "\n";
3434

35-
shmop_close($shm_id);
36-
3735
echo "shm open for read only: ";
3836
$shm_id = shmop_open($hex_shm_id, "a", 0644, 1024);
3937
if (!$shm_id) {
@@ -47,8 +45,6 @@ shmop extension test
4745
/* try to append data to the shared memory segment, this should fail */
4846
shmop_write($shm_id, $write_d1, $written);
4947

50-
shmop_close($shm_id);
51-
5248
echo "shm open for read only: ";
5349
$shm_id = shmop_open($hex_shm_id, "w", 0644, 1024);
5450
if (!$shm_id) {
@@ -73,8 +69,6 @@ shmop extension test
7369
} else {
7470
echo "ok\n";
7571
}
76-
77-
shmop_close($shm_id);
7872
?>
7973
--EXPECTF--
8074
shm open for create: ok

0 commit comments

Comments
 (0)