view release on metacpan or search on metacpan
1516171819202122232425262728293031323334
- Fix from Lars Thegler
for
buffer overrun in speedy_opt.c
- Add efence malloc debugging.
2.21 Thu Sep 26 15:27:35 PDT 2002
- Fix too many backends problem reported by Theo Petersen. The
problem is due to temp-file corruption that occurs
when
the
web-server sends a TERM signal to the frontend
while
it is working
on the temp file. It also results in some backends failing due
to the corruption. Added a fix so that signals are always blocked
while
working on the temp file.
- Shutdown handler should be called
after
script is touched.
- Fixes
for
Mac OS X 10.1. Workaround the sigpending() bug,
and add msync() which appears to fix a shared-memory flushing
problem
when
temp-file is expanded.
2.20 Wed Sep 11 19:33:36 PDT 2002
docs/file_struct.html view on Meta::CPAN
727374757677787980818283848586878889909192
</td>
<td>
Number of slots in the slot array.
</td>
</
tr
>
<
tr
>
<td>
file_corrupt
</td>
<td>
Boolean - is this file corrupt? This is true
if
a process locked
this file, but exited or was killed
before
unlocking it.
</td>
</
tr
>
<
tr
>
<td>
file_removed
</td>
<td>
Boolean -
has
this file been removed from the filesystem?
</td>
docs/prog_outline.txt view on Meta::CPAN
282930313233343536373839404142434445464748================
- While
no
connection:
- Stat
our
script file
- Call
"Get a Backend"
- If we got a backend:
- Try to
connect
- If connection successful,
return
- If connection failed:
- Unless there
's a bug in the code somewhere, this BE must'
ve
been killed and not yet cleaned up. Since we've already
unlocked the file,
if
we
try
to go
do
a cleanup, we may get
there
after
another process does. So, we may be overwriting
some other unrelated slot data instead. This could be
solved
with
some data in the BE slot where we allocate
this BE to
our
pid
before
unlocking, making us the only pid
allowed to clean it up. Or we could go back and track down
our
group/script again and find this BE on the group's list,
if
it's still there. But, both of these options are a lot
of trouble
for
what should be a rare occurance anyways -
if
the process is dead, the normal cleanup mechanism should
eventually get rid of it anyways (assuming
no
PID wrap).
docs/prog_outline.txt view on Meta::CPAN
172173174175176177178179180181182183184185186187188189190191192Frontend Dispose
================
- ???
File Operations
---------------
File Lock
=========
- If file is already locked,
return
.
- If file-descriptor is marked suspect:
- If file is
open
:
- Fstat the
open
file-descriptor
- If fstat fails or different dev/inode:
-
"Unmap the file"
- Forget this file-descriptor
- Endif
- Endif
- Mark file-descriptor OK
- Endif
src/speedy_file.c view on Meta::CPAN
171819202122232425262728293031323334353637*
*/
/* Open/create, mmap and
lock
the speedy temp file */
#include "speedy.h"
speedy_file_t
*speedy_file_maddr
;
static
int
file_fd = -1;
static
int
maplen;
static
int
file_locked;
static char
*file_name
,
*saved_tmpbase
;
static struct
stat
file_stat;
static
int
cur_state;
static time_t last_reopen;
#ifdef SPEEDY_BACKEND
static
int
fd_is_suspect;
#endif
#define fillin_fl(fl) \
fl.l_whence = SEEK_SET; \
src/speedy_file.c view on Meta::CPAN
7172737475767778798081828384858687888990919293949596979899
);
if
(speedy_file_maddr == (speedy_file_t*)MAP_FAILED)
speedy_util_die(
"mmap failed"
);
}
}
}
static void file_unlock(void) {
struct
flock
fl;
if
(!file_locked)
return
;
FILE_HEAD.lock_owner = 0;
fillin_fl(fl);
fl.l_type = F_UNLCK;
if
(
fcntl
(file_fd, F_SETLK,
&fl
) == -1) speedy_util_die(
"unlock file"
);
file_locked = 0;
speedy_sig_blockall_undo();
}
/* Only call this
if
you're sure the fd is not suspect */
static void file_close2(void) {
#ifdef SPEEDY_BACKEND
if
(fd_is_suspect)
DIE_QUIET(
"file_close2: assertion failed - fd_is_suspect"
);
src/speedy_file.c view on Meta::CPAN
161162163164165166167168169170171172173174175176177178179180181
speedy_free(
*ptr
);
*ptr
= newval;
}
static void file_lock(void) {
static struct timeval file_create_time;
struct
flock
fl;
int
tries;
time_t now;
if
(file_locked)
return
;
#ifdef SPEEDY_BACKEND
fix_suspect_fd();
#endif
/* Re-
open
the temp file occasionally or
if
tmpbase changed */
if
((now = speedy_util_time()) - last_reopen > OPTVAL_RESTATTIMEOUT ||
!saved_tmpbase || strcmp(saved_tmpbase, OPTVAL_TMPBASE) != 0)
{
src/speedy_file.c view on Meta::CPAN
193194195196197198199200201202203204205206207208209210211212213
);
if
(file_fd == -1) speedy_util_die(
"open temp file"
);
fcntl
(file_fd, F_SETFD, FD_CLOEXEC);
}
/* Lock the file */
fillin_fl(fl);
fl.l_type = F_WRLCK;
if
(
fcntl
(file_fd, F_SETLKW,
&fl
) == -1) speedy_util_die(
"lock file"
);
/* Fstat the file, now that it's locked down */
get_stat();
/* Map into memory */
file_map(file_stat.st_size);
/* If file is too small (0 or below MIN_SLOTS_FREE), extend it */
if
(file_stat.st_size < sizeof(file_head_t) ||
file_stat.st_size < sizeof(file_head_t) +
sizeof(slot_t) * (FILE_HEAD.slots_alloced + MIN_SLOTS_FREE))
{
src/speedy_file.c view on Meta::CPAN
239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
/* If file
has
not been removed then all done */
if
(!FILE_HEAD.file_removed)
break;
/* File is invalid */
if
(cur_state >= FS_HAVESLOTS) {
/* Too late
for
this proc - slotnums have changed, can't recover */
DIE_QUIET(
"temp file is corrupt"
);
}
else
{
/* Bad luck - the file was unlinked
after
we opened it (possibly
* by us because it was corrupt), but
before
we locked it.
* Try again.
*/
file_close2();
}
}
if
(!tries) {
DIE_QUIET(
"could not open temp file"
);
}
/* Block all sigs
while
writing to file */
speedy_sig_blockall();
file_locked = 1;
FILE_HEAD.lock_owner = speedy_util_getpid();
}
static void file_close(void) {
/* If
no
groups left, remove the file */
if
(cur_state >= FS_HAVESLOTS) {
file_lock();
if
(!FILE_HEAD.group_head && !FILE_HEAD.fe_run_head)
remove_file(0);
}
src/speedy_file.c view on Meta::CPAN
297298299300301302303304305306307308309310311312313314315316317318
int
retval = cur_state;
if
(new_state != cur_state) {
switch_state(new_state);
cur_state = new_state;
}
return
retval;
}
void speedy_file_fork_child(void) {
if
(file_locked)
speedy_sig_blockall_undo();
file_locked = 0;
if
(cur_state > FS_HAVESLOTS)
speedy_file_set_state(FS_HAVESLOTS);
}
#ifdef SPEEDY_BACKEND
void speedy_file_need_reopen(void) {
last_reopen = 0;
}
#endif
src/speedy_file.h view on Meta::CPAN
363738394041424344454647484950515253545556#define FILE_ALLOC_CHUNK 512
#define FILE_REV 6
#define FILE_HEAD (speedy_file_maddr->file_head)
#define FILE_SLOTS (speedy_file_maddr->slots)
#define FILE_SLOT(member, n) (FILE_SLOTS[SLOT_CHECK(n)-1].slot_u.member)
#define MIN_SLOTS_FREE 5
/* File access states */
#define FS_CLOSED 0 /* File is closed, not mapped */
#define FS_OPEN 1 /* Unlocked. Keep open for performance only */
#define FS_HAVESLOTS 2 /* Unlocked. We are holding onto slots in
this file */
#define FS_CORRUPT 3 /* Locked, mmaped, non-atomic writes to file */
extern speedy_file_t
*speedy_file_maddr
;
SPEEDY_INLINE void speedy_file_fd_is_suspect(void);
int
speedy_file_size(void);
SPEEDY_INLINE
int
speedy_file_set_state(
int
new_state);
void speedy_file_need_reopen(void);
void speedy_file_fork_child(void);
src/speedy_frontend.c view on Meta::CPAN
324325326327328329330331332333334335336337338339340341342343344
/* Unlock the file */
speedy_file_set_state(FS_HAVESLOTS);
/* Set an
alarm
for
one-second or so. */
alarm
(OPTVAL_BECHECKTIMEOUT);
/* Wait
for
a timeout or signal from backend */
speedy_sig_wait(
&sl
);
/* Find out
if
our
file changed. Do this
while
unlocked */
file_changed = speedy_script_changed();
/* Acquire
lock
. If group bad or file changed, then done */
if
(!speedy_group_lock(gslotnum) || file_changed)
break;
}
/* Remove
our
FE slot from the queue. */
speedy_slot_remove(fslotnum,
&(FILE_SLOT(gr_slot, gslotnum).fe_head),
src/speedy_group.h view on Meta::CPAN
1314151617181920212223242526272829303132*
* You should have received a copy of the GNU General Public License
* along
with
this program;
if
not,
write
to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
void speedy_group_invalidate(slotnum_t gslotnum);
void speedy_group_sendsigs(slotnum_t gslotnum);
void speedy_group_cleanup(slotnum_t gslotnum);
int
speedy_group_connect_locked(slotnum_t gslotnum);
slotnum_t speedy_group_create(void);
pid_t speedy_group_be_starting(slotnum_t gslotnum);
int
speedy_group_parent_sig(slotnum_t gslotnum,
int
sig);
int
speedy_group_start_be(slotnum_t gslotnum);
int
speedy_group_lock(slotnum_t gslotnum);
#define speedy_group_name_match(gslotnum) \
(FILE_SLOT(gr_slot, (gslotnum)).name_slot && \
!strncmp(FILE_SLOT(grnm_slot, FILE_SLOT(gr_slot, (gslotnum)).name_slot).name, OPTVAL_GROUP, GR_NAMELEN))
src/speedy_perl.c view on Meta::CPAN
406407408409410411412413414415416417418419420421422423424425426
perl_destruct(my_perl);
}
speedy_util_exit(0,0);
}
/* Wait
for
a connection from a frontend */
static void backend_accept(void) {
SigList sl;
int
ok;
/* Set up caught/unblocked signals to
exit
on */
speedy_sig_init(
&sl
, caught_sigs, NUMSIGS, SIG_UNBLOCK);
/* Wait
for
an
accept
or timeout */
ok = speedy_ipc_accept(OPTVAL_TIMEOUT*1000);
/* Put signals back to original settings */
speedy_sig_free(
&sl
);
/* If timed out or signal, then finish up */
if
(!ok)
src/speedy_sig.c view on Meta::CPAN
181920212223242526272829303132333435363738394041424344454647484950*/
#include "speedy.h"
/*
* Signal handling routines
*/
static volatile
int
got_sig[SPEEDY_MAXSIG];
static sigset_t blockall_save;
static
int
all_blocked;
void speedy_sig_blockall(void) {
sigset_t full_set;
sigfillset(
&full_set
);
sigprocmask(SIG_BLOCK,
&full_set
,
&blockall_save
);
all_blocked = 1;
}
void speedy_sig_blockall_undo(void) {
sigprocmask(SIG_SETMASK,
&blockall_save
, NULL);
all_blocked = 0;
}
static
int
sig_find(const volatile
int
sig_rcvd[SPEEDY_MAXSIG],
int
sig) {
register
int
i;
for
(i = 0; i < SPEEDY_MAXSIG && sig_rcvd[i]; ++i) {
if
(sig_rcvd[i] == sig)
return
-1;
}
return
i;
src/speedy_sig.c view on Meta::CPAN
828384858687888990919293949596979899100101102{
struct sigaction sigact;
sigact.sa_handler =
&sig_handler
;
sigact.sa_flags = 0;
sigemptyset(
&sigact
.sa_mask);
for
(i = 0; i < sl->numsigs; ++i)
sigaction(sl->signum[i],
&sigact
, &(sl->sigact_save[i]));
}
/* Block or unblock
our
signals. Save original mask */
if
(all_blocked) {
sl->sigset_save = blockall_save;
for
(i = 0; i < sl->numsigs; ++i) {
if
(how == SIG_BLOCK)
sigaddset(
&blockall_save
, sl->signum[i]);
else
sigdelset(
&blockall_save
, sl->signum[i]);
}
}
else
{
sigset_t block_sigs;
sigemptyset(
&block_sigs
);
src/speedy_sig.c view on Meta::CPAN
120121122123124125126127128129130131132133134135136137138139140
sl->numsigs = numsigs;
/* Finish init */
sig_init2(sl, how);
}
void speedy_sig_free(const SigList
*sl
) {
int
i;
/* Get rid of any pending signals. On Sun/apache-2 we don't get pending
* signals as soon as they are unblocked - instead they get delivered
*
after
the action is restored, which is not what we want.
*/
do
{
sigset_t set;
/* Bug in Mac OS X 10.1 and earlier - sigpending is essentially a
*
no
-op, so we get garbage, and get stuck in sigsuspend.
* Workaround by clearing out the set initially so we get
no
pending
* signals back.
*/
src/speedy_sig.c view on Meta::CPAN
144145146147148149150151152153154155156157158159160161162
break;
for
(i = 0; i < sl->numsigs; ++i) {
if
(sigismember(
&set
, sl->signum[i])) {
sig_wait_basic(sl);
break;
}
}
}
while
(i < sl->numsigs);
/* Unblock sigs */
if
(all_blocked)
blockall_save = sl->sigset_save;
else
sigprocmask(SIG_SETMASK,
&sl
->sigset_save, NULL);
/* Install old handlers */
for
(i = 0; i < sl->numsigs; ++i)
sigaction(sl->signum[i], &(sl->sigact_save[i]), NULL);
}
src/speedy_slot.c view on Meta::CPAN
8990919293949596979899100101102103104105106107108109110}
else
{
/* Allocate a new slot */
slotnum = FILE_HEAD.slots_alloced + 1;
/* Abort
if
too many slots */
if
(slotnum >= MAX_SLOTS)
DIE_QUIET(
"Out of slots"
);
/* Check here
if
the file is large enough to hold this slot.
* The speedy_file code is supposed to allocate enough extra
* slots (MIN_SLOTS_FREE)
when
the file is locked to satisfy
* all slot_alloc's
until
the file is unlocked. But
if
the
* code starts allocating too many slots
for
whatever reason,
* that will not work, and we'll drop off the end of the file.
* In that case, either fix the code or bump MIN_SLOTS_FREE
*/
if
(sizeof(file_head_t)+slotnum
*sizeof
(slot_t) > speedy_file_size()) {
speedy_util_die(
"File too small for another slot while allocating slotnum %d. File size=%d. Try increasing MIN_SLOTS_FREE."
,
slotnum, speedy_file_size()
);
}