2 # Shm.pl: Shared Memory stuff.
15 if (&IsParam("noSHM")) {
16 &status("Created shared memory: disabled. [bot may become unreliable]");
20 if (defined( $_ = shmget($IPC_PRIVATE, $size, 0777) )) {
21 &status("Created shared memory (shm) key: [$_]");
24 &ERROR("openSHM: failed.");
25 &ERROR("Please delete some shared memory with ipcs or ipcrm.");
34 return '' if (!defined $key);
37 &status("Closed shared memory (shm) key: [$key]");
38 return shmctl($key, $IPC_RMID, 0);
47 return '' if (&IsParam("noSHM"));
49 if (shmread($key,$retval,$position,$size)) {
52 &ERROR("shmRead: failed: $!");
53 ### TODO: if this fails, never try again.
64 return if (&IsParam("noSHM"));
67 ### TODO: create shmClear to deal with this.
69 my $read = &shmRead($key);
73 $str = time().": "; # time stamping, null.
74 } elsif ($read eq "") {
75 $str = time().": "; # timestamping.
77 $str = $read ."||". $str;
81 if (!shmwrite($key,$str,$position,$size)) {
82 &ERROR("shmWrite: failed: $!");
90 # Usage: &addForked($name);
91 # Return: 1 for success, 0 for failure.
94 my $forker_timeout = 360; # 6mins, in seconds.
98 &WARN("addForked: name == NULL.");
102 foreach (keys %forked) {
104 my $time = time() - $forked{$n}{Time};
105 next unless ($time > $forker_timeout);
107 ### TODO: use &time2string()?
108 &WARN("Fork: looks like we lost '$n', executed $time ago");
110 my $pid = $forked{$n}{PID};
112 &WARN("Fork: no pid for $n.");
119 &status("Fork: pid == \$\$ ($$)");
123 if ( -d "/proc/$pid") {
124 &status("Fork: killing $name ($pid)");
132 while (scalar keys %forked > 1) { # 2 or more == fail.
135 if ($count > 3) { # 3 seconds.
136 my $list = join(', ', keys %forked);
138 &msg($who, "already running ($list) => exceeded allowed forked processes count (1?).");
140 &status("Fork: I ran too many forked processes :) Giving up $name.");
148 if (exists $forked{$name} and !scalar keys %{ $forked{$name} }) {
149 &WARN("addF: forked{$name} exists but is empty; deleting.");
150 undef $forked{$name};
153 if (exists $forked{$name} and scalar keys %{ $forked{$name} }) {
154 my $time = $forked{$name}{Time};
157 $continue++ if ($forked{$name}{PID} == $$);
160 &WARN("hrm.. fork pid == mypid == $$; how did this happen?");
162 } elsif ( -d "/proc/$forked{$name}{PID}") {
163 &status("fork: still running; good. BAIL OUT.");
167 &WARN("Found dead fork; removing and resetting.");
174 } elsif (time() - $time > 900) { # stale fork > 15m.
175 &status("forked: forked{$name} presumably exited without notifying us.");
177 } else { # fresh fork.
178 &msg($who, "$name is already running ". &Time2String(time() - $time));
183 $forked{$name}{Time} = time();
184 $forked{$name}{PID} = $$;
185 $forkedtime = time();
193 return if ($$ == $bot_pid);
195 if (!defined $name) {
196 &WARN("delForked: name == NULL.");
200 if ($name =~ /\.pl/) {
201 &WARN("dF: name is name of source file ($name). FIX IT!");
204 &showProc(); # just for informational purposes.
206 if (exists $forked{$name}) {
207 my $timestr = &Time2String(time() - $forked{$name}{Time});
208 &status("fork: took $timestr for $name.");
209 &shmWrite($shm,"DELETE FORK $name");
211 &ERROR("delForked: forked{$name} does not exist. should not happen.");
214 &status("--- fork finished for '$name' ---");