Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2a44383

Browse files
committed
Clean up memory leaks in LO operations by freeing LO's private
memory context at transaction commit or abort.
1 parent81ced1e commit2a44383

File tree

3 files changed

+83
-28
lines changed

3 files changed

+83
-28
lines changed

‎src/backend/access/transam/xact.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.36 1999/05/25 16:07:50 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.37 1999/05/31 22:53:59 tgl Exp $
1111
*
1212
* NOTES
1313
*Transaction aborts can now occur two ways:
@@ -156,8 +156,6 @@
156156
#include<miscadmin.h>
157157
#include<commands/async.h>
158158
#include<commands/sequence.h>
159-
160-
/* included for _lo_commit [PA, 7/17/98] */
161159
#include<libpq/be-fsstubs.h>
162160

163161
staticvoidAbortTransaction(void);
@@ -938,7 +936,7 @@ CommitTransaction()
938936
*/
939937

940938
/* handle commit for large objects [ PA, 7/17/98 ] */
941-
_lo_commit();
939+
lo_commit(true);
942940

943941
/* NOTIFY commit must also come before lower-level cleanup */
944942
AtCommit_Notify();
@@ -1012,6 +1010,7 @@ AbortTransaction()
10121010
*do abort processing
10131011
* ----------------
10141012
*/
1013+
lo_commit(false);/* 'false' means it's abort */
10151014
UnlockBuffers();
10161015
AtAbort_Notify();
10171016
CloseSequences();

‎src/backend/libpq/be-fsstubs.c

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,25 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.33 1999/05/25 16:08:57momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.34 1999/05/31 22:53:57tgl Exp $
1111
*
1212
* NOTES
1313
* This should be moved to a more appropriate place. It is here
1414
* for lack of a better place.
1515
*
1616
* Builtin functions for open/close/read/write operations on large objects.
1717
*
18-
* These functions operate in the current portal variable context, which
19-
* means the large object descriptors hang around between transactions and
20-
* are not deallocated until explicitly closed, or until the portal is
21-
* closed.
18+
* These functions operate in a private GlobalMemoryContext, which means
19+
* that large object descriptors hang around until we destroy the context.
20+
* That happens in lo_commit(). It'd be possible to prolong the lifetime
21+
* of the context so that LO FDs are good across transactions (for example,
22+
* we could release the context only if we see that no FDs remain open).
23+
* But we'd need additional state in order to do the right thing at the
24+
* end of an aborted transaction. FDs opened during an aborted xact would
25+
* still need to be closed, since they might not be pointing at valid
26+
* relations at all. For now, we'll stick with the existing documented
27+
* semantics of LO FDs: they're only good within a transaction.
28+
*
2229
*-------------------------------------------------------------------------
2330
*/
2431

@@ -37,6 +44,7 @@
3744
#include<utils/memutils.h>
3845
#include<lib/fstack.h>
3946
#include<utils/mcxt.h>
47+
#include<catalog/pg_shadow.h>/* for superuser() */
4048
#include<storage/fd.h>/* for O_ */
4149
#include<storage/large_object.h>
4250
#include<libpq/be-fsstubs.h>
@@ -91,6 +99,11 @@ lo_open(Oid lobjId, int mode)
9199
/* switch context back to orig. */
92100
MemoryContextSwitchTo(currentContext);
93101

102+
#ifFSDB
103+
if (fd<0)/* newLOfd couldn't find a slot */
104+
elog(NOTICE,"Out of space for large object FDs");
105+
#endif
106+
94107
returnfd;
95108
}
96109

@@ -144,6 +157,8 @@ lo_read(int fd, char *buf, int len)
144157
elog(ERROR,"lo_read: invalid large obj descriptor (%d)",fd);
145158
return-3;
146159
}
160+
161+
Assert(fscxt!=NULL);
147162
currentContext=MemoryContextSwitchTo((MemoryContext)fscxt);
148163

149164
status=inv_read(cookies[fd],buf,len);
@@ -168,6 +183,8 @@ lo_write(int fd, char *buf, int len)
168183
elog(ERROR,"lo_write: invalid large obj descriptor (%d)",fd);
169184
return-3;
170185
}
186+
187+
Assert(fscxt!=NULL);
171188
currentContext=MemoryContextSwitchTo((MemoryContext)fscxt);
172189

173190
status=inv_write(cookies[fd],buf,len);
@@ -181,7 +198,7 @@ int
181198
lo_lseek(intfd,intoffset,intwhence)
182199
{
183200
MemoryContextcurrentContext;
184-
intret;
201+
intstatus;
185202

186203
if (fd<0||fd >=MAX_LOBJ_FDS)
187204
{
@@ -194,13 +211,14 @@ lo_lseek(int fd, int offset, int whence)
194211
return-3;
195212
}
196213

214+
Assert(fscxt!=NULL);
197215
currentContext=MemoryContextSwitchTo((MemoryContext)fscxt);
198216

199-
ret=inv_seek(cookies[fd],offset,whence);
217+
status=inv_seek(cookies[fd],offset,whence);
200218

201219
MemoryContextSwitchTo(currentContext);
202220

203-
returnret;
221+
returnstatus;
204222
}
205223

206224
Oid
@@ -246,12 +264,26 @@ lo_tell(int fd)
246264
elog(ERROR,"lo_tell: invalid large object descriptor (%d)",fd);
247265
return-3;
248266
}
267+
268+
/*
269+
* We assume we do not need to switch contexts for inv_tell.
270+
* That is true for now, but is probably more than this module
271+
* ought to assume...
272+
*/
249273
returninv_tell(cookies[fd]);
250274
}
251275

252276
int
253277
lo_unlink(OidlobjId)
254278
{
279+
/*
280+
* inv_destroy does not need a context switch, indeed it doesn't
281+
* touch any LO-specific data structures at all. (Again, that's
282+
* probably more than this module ought to be assuming.)
283+
*
284+
* XXX there ought to be some code to clean up any open LOs that
285+
* reference the specified relation... as is, they remain "open".
286+
*/
255287
returninv_destroy(lobjId);
256288
}
257289

@@ -297,24 +329,31 @@ lo_import(text *filename)
297329
Filefd;
298330
intnbytes,
299331
tmp;
300-
301332
charbuf[BUFSIZE];
302333
charfnamebuf[FNAME_BUFSIZE];
303334
LargeObjectDesc*lobj;
304335
OidlobjOid;
305336

337+
if (!superuser())
338+
elog(ERROR,"You must have Postgres superuser privilege to use "
339+
"server-side lo_import().\n\tAnyone can use the "
340+
"client-side lo_import() provided by libpq.");
341+
306342
/*
307343
* open the file to be read in
308344
*/
309-
StrNCpy(fnamebuf,VARDATA(filename),VARSIZE(filename)-VARHDRSZ+1);
345+
nbytes=VARSIZE(filename)-VARHDRSZ+1;
346+
if (nbytes>FNAME_BUFSIZE)
347+
nbytes=FNAME_BUFSIZE;
348+
StrNCpy(fnamebuf,VARDATA(filename),nbytes);
310349
#ifndef__CYGWIN32__
311350
fd=PathNameOpenFile(fnamebuf,O_RDONLY,0666);
312351
#else
313352
fd=PathNameOpenFile(fnamebuf,O_RDONLY |O_BINARY,0666);
314353
#endif
315354
if (fd<0)
316355
{/* error */
317-
elog(ERROR,"be_lo_import: can't open unix file \"%s\"\n",
356+
elog(ERROR,"lo_import: can't open unix file \"%s\": %m",
318357
fnamebuf);
319358
}
320359

@@ -341,10 +380,8 @@ lo_import(text *filename)
341380
{
342381
tmp=inv_write(lobj,buf,nbytes);
343382
if (tmp<nbytes)
344-
{
345383
elog(ERROR,"lo_import: error while reading \"%s\"",
346384
fnamebuf);
347-
}
348385
}
349386

350387
FileClose(fd);
@@ -363,12 +400,16 @@ lo_export(Oid lobjId, text *filename)
363400
Filefd;
364401
intnbytes,
365402
tmp;
366-
367403
charbuf[BUFSIZE];
368404
charfnamebuf[FNAME_BUFSIZE];
369405
LargeObjectDesc*lobj;
370406
mode_toumask;
371407

408+
if (!superuser())
409+
elog(ERROR,"You must have Postgres superuser privilege to use "
410+
"server-side lo_export().\n\tAnyone can use the "
411+
"client-side lo_export() provided by libpq.");
412+
372413
/*
373414
* open the inversion "object"
374415
*/
@@ -378,9 +419,16 @@ lo_export(Oid lobjId, text *filename)
378419

379420
/*
380421
* open the file to be written to
422+
*
423+
* Note: we reduce backend's normal 077 umask to the slightly
424+
* friendlier 022. This code used to drop it all the way to 0,
425+
* but creating world-writable export files doesn't seem wise.
381426
*/
382-
StrNCpy(fnamebuf,VARDATA(filename),VARSIZE(filename)-VARHDRSZ+1);
383-
oumask=umask((mode_t)0);
427+
nbytes=VARSIZE(filename)-VARHDRSZ+1;
428+
if (nbytes>FNAME_BUFSIZE)
429+
nbytes=FNAME_BUFSIZE;
430+
StrNCpy(fnamebuf,VARDATA(filename),nbytes);
431+
oumask=umask((mode_t)0022);
384432
#ifndef__CYGWIN32__
385433
fd=PathNameOpenFile(fnamebuf,O_CREAT |O_WRONLY |O_TRUNC,0666);
386434
#else
@@ -389,7 +437,7 @@ lo_export(Oid lobjId, text *filename)
389437
umask(oumask);
390438
if (fd<0)
391439
{/* error */
392-
elog(ERROR,"lo_export: can't open unix file \"%s\"",
440+
elog(ERROR,"lo_export: can't open unix file \"%s\": %m",
393441
fnamebuf);
394442
}
395443

@@ -400,10 +448,8 @@ lo_export(Oid lobjId, text *filename)
400448
{
401449
tmp=FileWrite(fd,buf,nbytes);
402450
if (tmp<nbytes)
403-
{
404451
elog(ERROR,"lo_export: error while writing \"%s\"",
405452
fnamebuf);
406-
}
407453
}
408454

409455
inv_close(lobj);
@@ -417,24 +463,34 @@ lo_export(Oid lobjId, text *filename)
417463
* prepares large objects for transaction commit [PA, 7/17/98]
418464
*/
419465
void
420-
_lo_commit(void)
466+
lo_commit(boolisCommit)
421467
{
422468
inti;
423469
MemoryContextcurrentContext;
424470

425471
if (fscxt==NULL)
426-
return;
472+
return;/* no LO operations in this xact */
427473

428474
currentContext=MemoryContextSwitchTo((MemoryContext)fscxt);
429475

476+
/* Clean out still-open index scans (not necessary if aborting)
477+
* and clear cookies array so that LO fds are no longer good.
478+
*/
430479
for (i=0;i<MAX_LOBJ_FDS;i++)
431480
{
432481
if (cookies[i]!=NULL)
433-
inv_cleanindex(cookies[i]);
482+
{
483+
if (isCommit)
484+
inv_cleanindex(cookies[i]);
485+
cookies[i]=NULL;
486+
}
434487
}
435488

436489
MemoryContextSwitchTo(currentContext);
437490

491+
/* Release the LO memory context to prevent permanent memory leaks. */
492+
GlobalMemoryDestroy(fscxt);
493+
fscxt=NULL;
438494
}
439495

440496

‎src/include/libpq/be-fsstubs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: be-fsstubs.h,v 1.8 1999/02/13 23:21:34 momjian Exp $
9+
* $Id: be-fsstubs.h,v 1.9 1999/05/31 22:53:58 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -40,6 +40,6 @@ extern intlowrite(int fd, struct varlena * wbuf);
4040
/*
4141
* Added for buffer leak prevention [ Pascal André <andre@via.ecp.fr> ]
4242
*/
43-
externvoid_lo_commit(void);
43+
externvoidlo_commit(boolisCommit);
4444

4545
#endif/* BE_FSSTUBS_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp