The attached patch is an attempt to fix some of the use of unsafe
functions in the daemon.  It also fixes it in basep, for comparison.

Unsafe functions are those that may not be called in the context of a
signal handler.  The "man signal" page lists them.  The existing code
calls some of these functions from within the alarm signal handler
move() in daemonII.c.  

Please review and comment.

Testing has been limited ... a minute of play against "*" robots.

The patch is also in my repository:

My plan is to extend the feature to the remaining uses of SIGALRM in
particular, and other signal functions as I locate them.  I may also
ponder the exitDaemon function, although this isn't as critical.

Design features:

- the use of SIGALRM is placed into a single file, alarm.c in ntserv/,
  with a new prototype file alarm.h in include/,

- rather than executing the body of the processing in signal context,
  the main loop is altered so that a counter is incremented when a
  signal is received,

- the pause(2) call in the main loop is augmented with a check of the
  counter, and at this point the function that used to be the signal
  handler is executed.

[fix use of unsafe functions in signal handler, daemon, basep
quozl at**20060823014948
        * alarm.c, alarm.h: merge common alarm signal handling functions.
        * basep.c, daemonII.c: use common functions and change main loop to
          execute always in non-signal context.

James Cameron    mailto:quozl at
-------------- next part --------------

New patches:

[fix use of unsafe functions in signal handler, daemon, basep
quozl at**20060823014948
 	* alarm.c, alarm.h: merge common alarm signal handling functions.
 	* basep.c, daemonII.c: use common functions and change main loop to
 	  execute always in non-signal context.
> {
addfile ./Vanilla/include/alarm.h
hunk ./Vanilla/include/alarm.h 1
+void alarm_init();
+void alarm_set();
+void alarm_ignore();
+void alarm_prevent_inheritance();
+void alarm_handler(int signum);
+void alarm_wait_for();
hunk ./Vanilla/ntserv/ 16
 #	libnetrek object files
-L_OBJS = balance.o bans.o bay.o \
+L_OBJS = alarm.o balance.o bans.o bay.o \
 	coup.o \
 	data.o db.o detonate.o distress.o \
 	enter.o \
addfile ./Vanilla/ntserv/alarm.c
hunk ./Vanilla/ntserv/alarm.c 1
+#include <sys/wait.h>
+#include "defs.h"
+#include "alarm.h"
+#include INC_UNISTD
+/* alarm signal functions */
+int alarm_count;
+void alarm_set();
+void alarm_handler(int signum);
+void alarm_init()
+  alarm_count = 0;
+  alarm_set();
+void alarm_set()
+  (void) SIGNAL(SIGALRM, alarm_handler);
+void alarm_ignore()
+void alarm_prevent_inheritance()
+void alarm_handler(int signum)
+  alarm_count++;
+  alarm_set();
+void alarm_wait_for()
+  while (1) {
+    if (alarm_count--) return;
+  }
hunk ./Vanilla/ntserv/daemonII.c 20
 #include "proto.h"
 #include "conquer.h"
 #include "daemon.h"
+#include "alarm.h"
 #include INC_UNISTD
 #include INC_SYS_FCNTL
hunk ./Vanilla/ntserv/daemonII.c 62
 static void check_load(void);
 static int tournamentMode(void);
 static int check_scummers(int);
-static void move(int ignored);
+static void move();
 static void udplayersight(void);
 static void udplayers(void);
 static void udplayerpause(void);
hunk ./Vanilla/ntserv/daemonII.c 270
 #endif /*PUCK_FIRST*/
-    (void) SIGNAL(SIGALRM, move);
+    alarm_init();
     udt.it_interval.tv_sec = 0;
     udt.it_interval.tv_usec = reality;
     udt.it_value.tv_sec = 0;
hunk ./Vanilla/ntserv/daemonII.c 287
     x = 0;
     for (;;) {
-        PAUSE(SIGALRM);
+        alarm_wait_for();
+        move();
         if (debug) {
             if (!(++x % 50))
                 ERROR(1,("Mark %d\n", x));
hunk ./Vanilla/ntserv/daemonII.c 539
-static void move(int ignored)
+static void move()
     static int oldmessage;
     int old_robot;
hunk ./Vanilla/ntserv/daemonII.c 551
     } ts = TS_PICKUP;
-    /* Don't tell us it's time for another move in the middle of a move. */
     if (fuse(QUEUEFUSE)){
hunk ./Vanilla/ntserv/daemonII.c 562
       if (status->gameup & GU_CONQUER) conquer_update();
-      (void) SIGNAL(SIGALRM, move);
hunk ./Vanilla/ntserv/daemonII.c 716
     if (fuse(CHECKLOADFUSE)) {
-    (void) SIGNAL(SIGALRM, move);
-    if (ignored) ;
hunk ./Vanilla/ntserv/daemonII.c 3466
-    (void) SIGNAL(SIGALRM, SIG_IGN);     /* ignore timer signal */
     /* if problem occured before shared memory setup */
     if (!players)
hunk ./Vanilla/ntserv/daemonII.c 3973
             (void) close(1);
             (void) close(2);
-        (void) SIGNAL(SIGALRM, SIG_DFL);
+        alarm_prevent_inheritance();
         argv[argc++] = "robot";
         switch (team) {
           case FED:
hunk ./Vanilla/ntserv/daemonII.c 4219
 static void fork_robot(int robot)
    if ((robot_pid=vfork()) == 0) {
-      (void) SIGNAL(SIGALRM, SIG_DFL);
+      alarm_prevent_inheritance();
       switch(robot) {
         case NO_ROBOT: break;
hunk ./Vanilla/ntserv/daemonII.c 4437
     if (puckwait)
-        SIGNAL(SIGALRM, do_nuttin);
         semop(pucksem_id, pucksem_op, 1);
hunk ./Vanilla/ntserv/daemonII.c 4438
 #endif /*PUCK_FIRST*/
hunk ./Vanilla/robots/basep.c 31
 #include "struct.h"
 #include "data.h"
 #include "proto.h"
+#include "alarm.h"
 #include "roboshar.h"
 #include "basepdefs.h"
hunk ./Vanilla/robots/basep.c 77
 void cleanup(int);
-void checkmess(int);
+void checkmess();
 int rprog(char *login, char *monitor);
 void start_internal();
 void exitRobot();
hunk ./Vanilla/robots/basep.c 86
 void startrobot(int num, char *s, char *h, char *log, int dg, int base, int def);
 void fix_planets();
-   int	sig;
+static void reaper(int sig)
    int stat=0;
hunk ./Vanilla/robots/basep.c 89
-   static int pid;
+   int pid;
    while ((pid = WAIT3(&stat, WNOHANG, 0)) > 0) ;
hunk ./Vanilla/robots/basep.c 117
-   SIGNAL(SIGALRM, checkmess);             /*the def signal is needed - MK */
+   alarm_init();
    if (!debug)
        SIGNAL(SIGINT, cleanup);
hunk ./Vanilla/robots/basep.c 155
    status->gameup |= GU_CHAOS;
    status->gameup |= GU_PRACTICE;
-   /* Robot is signalled by the Daemon */
-   ERROR(3,("\nRobot Using Daemon Synchronization Timing\n"));
    me->p_process = getpid();
    me->p_timerdelay = HOWOFTEN; 
hunk ./Vanilla/robots/basep.c 164
     me->p_status = PALIVE;              /* Put robot in game */
     while (1) {
-        PAUSE(SIGALRM);
+        alarm_wait_for();
+        checkmess();
hunk ./Vanilla/robots/basep.c 169
-void checkmess(int unused)
+void checkmess()
    int 	shmemKey = PKEY;
hunk ./Vanilla/robots/basep.c 173
-    HANDLE_SIG(SIGALRM,checkmess);
     me->p_ghostbuster = 0;         /* keep ghostbuster away */
     if (me->p_status != PALIVE){  /*So I'm not alive now...*/
       ERROR(2,("ERROR: Smack died??\n"));
hunk ./Vanilla/robots/basep.c 456
       if (fork() == 0) {
+	 alarm_prevent_inheritance();
 	 execl("/bin/sh", "sh", "-c", command, (char *) NULL);
hunk ./Vanilla/robots/basep.c 490
     argv[argc] = NULL;
     if (fork() == 0) {
+	alarm_prevent_inheritance();
hunk ./Vanilla/robots/basep.c 532
 void exitRobot()
     if (me != NULL && me->p_team != ALLTEAM) {
         if (target >= 0) {
             messAll(255,roboname, "I'll be back.");


[Addition of missing options to sample sysdef, review
quozl at**20060822234537] 
[Addition of missing options to sample sysdef
williamb at**20060822220143
           * Adds 4 options that were in sysdefaults but missing from sysdef.
 M ./Vanilla/docs/ +12
[Adding vote tag to voting command structure
williamb at**20060822150841
        * gencmds.h: Formalizes the definition of C_PR_INPICKUP, and adds a new tag C_PR_VOTE
          gencmds.c (do_help): Only list vote commands if VOTING is set in sysdef
          ntscmds.c (struct command_handler_2 nts_commands): Adds C_PR_VOTE tag to the vote commands.
 	 Removes redefinition of C_PR_INPICKUP, as this is now defined in gencmds.h
 M ./Vanilla/include/gencmds.h -6 +7
 M ./Vanilla/ntserv/gencmds.c -1 +3
 M ./Vanilla/ntserv/ntscmds.c -10 +8
[Remove ability to vote if VOTING=0
williamb at**20060822152504
        * gencmds.c (check_2_command)  If a command is tagged as a vote, voting must be turned on
 	 for the command to execute.  This fixes a bug where if voting was off, vote commands could
 	 still be used, and they would pass with just 1 vote.
 M ./Vanilla/ntserv/gencmds.c +2
[Dogfight map file fix
williamb at**20060822175951
           * marsdefs.h: Correctly defines mapfile (it no longer has the leading period in filename).
 M ./Vanilla/robots/marsdefs.h -1 +1
[Ban vote duration in sample sysdef, review
quozl at**20060822232047
 	* docs/ add back lost text caused by my editing
 	  sample_sysdef instead of
[Ban vote duration in sample sysdef
williamb at**20060822124035
           * ( Adds BAN_VOTE_DURATION.
 M ./Vanilla/docs/ +5
[Improved tracking of server modes, review
quozl at**20060822231413] 
[Improved tracking of server modes
williamb at**20060822203642
 The purpose of this patch is to keep better track of what sort of robot mode the server is running,
 and to make consistent use of the server status states defined in struct.h.  This makes the code
 easier to understand in some places (especially regarding the inl robot), and it allows for a 
 smarter vote system, as votes will no longer pass if the server is already running the mode voted
 on.  This enhances server stability in the case of rapid switching between modes (dogfight, hockey,
 basepractice, and inl).  The server will no longer get "stuck" in a hockey galaxy, which has
 happened in the past when hockey was voted on twice.  Likewise for getting "stuck" in dogfight mode.
 The initial startup robot mode, as defined in sysdef, is also recognized, and that mode is not able 
 to be voted again until that robot exits.  There should now never be the case where there are 
 simultaneous duplicate robots, i.e. 2 hockey announcers, 2 SMACK basepractice starters, etc.
       * struct.h: Addition of GU_PUCK and GU_DOG server status.  Addition of server mode defines.
 	conquer.c, daemonII.c, death.c, getname.c, solicit.c, players.c: Replace compound bit
 	statements with server mode defines.
 	mars.c, marsmove.c, puck.c, puckmove.c: Track server status with new GU defines.
 	ntscmds.c: Add check before launching puck, mars, newbie, or pre_t robots.
 M ./Vanilla/include/struct.h -4 +10
 M ./Vanilla/ntserv/conquer.c -2 +2
 M ./Vanilla/ntserv/daemonII.c -7 +7
 M ./Vanilla/ntserv/death.c -1 +1
 M ./Vanilla/ntserv/getname.c -1 +1
 M ./Vanilla/ntserv/ntscmds.c -1 +21
 M ./Vanilla/ntserv/solicit.c -10 +8
 M ./Vanilla/robots/mars.c +1
 M ./Vanilla/robots/marsmove.c -1 +1
 M ./Vanilla/robots/puck.c +1
 M ./Vanilla/robots/puckmove.c +1
 M ./Vanilla/tools/players.c -1 +1
[Newbie server documentation update2
williamb at**20060822032823
          * INSTALL.Newbie - mention observer port, and point to robot command file
 M ./Vanilla/INSTALL.Newbie +3
[comindico whitelist removal, quozl specific
quozl at**20060818020653] 
[noted new bug, signal handler calls unsafe functions
quozl at**20060818002307] 
[initial design of checkpointing
quozl at**20060817015947
 	* PROJECTS.checkpointing: an initial design for checkpointing support
 	  that should allow live changes to code.
[add ban tools
quozl at**20060815042103
 	* tools/ban.c: add tool to display ban list, ban a player from command
 	  line, dump the list, and reload the list.
 	* tools/ add new ban program.
[add ban vote duration
quozl at**20060815031242
 	* include/data.h, ntserv/data.c, include/sysdefaults.h: add new
 	  BAN_VOTE_DURATION sysdef option.
 	* ntserv/main.c, ntscmds.c,, proto.h, bans.c: move ban
 	  logic into one source file.
 	* daemonII.c: every minute, age the temporary bans.
[add live daemon release target
quozl at**20060809070952
 	* ntserv/ add target to release a new daemon, though it
 	does not replace the running daemon.  That's an idea for later.
[fix test to correctly reproduce parade ring overlap
quozl at**20060809055741] 
[fix for conquer parade alignment, alternate
quozl at**20060809043954
 	* ntserv/conquer.c (conquer_ships_ring, conquer_parade): add a counter
 	for calculating ring coordinates rather than using player list position.
[add test for conquer parade slot alignment bug
quozl at**20060808054700
 	* tests/parade-bug-2006-08-07: a test to try to reproduce the
 	bug reported by Niclas where iggy slots end up in the same screen
 	position as player slots.
[add planet orbit and take test scripts
quozl at**20060808054456
 	* tools/setplanet.c: add be-orbited-by and be-taken-by test
 	actions, for use by test scripts.  They cheat, and are therefore
 	not intended for production use.
[minor indentation fixes prior to review
quozl at**20060808002418
 	* ntserv/conquer.c: tabify, some added lines lacked tabs, made it
[Semi-critical update fix
williamb at**20060622022126
       * socket.c (updateClient): clarifies purpose of packet type check against 0x40, adds check
         for SP_S_YOU case.
[Show geno messages for observers
williamb at**20060622013521
        * genspkt.c (sndSelf and sndSSelf):
          Factorized check for whether packet should be marked as critical.
          (check_sendself_critical): New function.
          Player status (via sndPStatus) is sent before player whydead (via sndSelf
          or sndSSelf).  When whydead changes, the packet must be marked as critical in
          order for that information to arrive first, so that observers can get a proper
          whydead message upon genocide.  This was previously done for just sndSelf, but
          with this patch, both sndSelf and sndSSelf now do it, and observers get geno
          messages with short packets on.
[Formatting fix for if statement in interface.c
williamb at**20060707151641
           * interface.c: (do_refit).  Fixes if statement split over 3 lines.
[Command file for PreT robots
williamb at**20060707152531
         * robots/pret.c: (start_a_robot) Adds the ability to read in a command file, as
           per the command file defined in pretdefs.h, but which was unused for whatever reason.          Note that both the newbie server and basepractice server are set to use the same
           file, defined as COMFILE in pretdefs.h, basepdefs.h, and newbiedefs.h.  As these
           modes are mutually exclusive, it is ok for them to read in robot commands from
           the same commands file.
 M ./Vanilla/robots/pret.c -1 +3
[adjust test scripts for xtkill changes
quozl at**20060710014703
 	* tests: some scripts used "xtkill k" repeatedly to grant kills,
 	changed to use the additional parameter.  Note that this additional
 	parameter is not immediately after the option, like it is with T or t
[Xtkill settable kills
williamb at**20060707153051
           * xtkill.c (main): Adds the ability to specify the number of kills to increment
             the player, identical to how the increment armies option works, rather than 
             just adding +1 kill per use of the xtkill k option.
 M ./Vanilla/tools/xtkill.c -2 +5
[Xtkill bug fixes
williamb at**20060623040057
         * xtkill.c (Usage): Added 2 missing options (u and H) to options list.
           (main): Removed call to getshipdefaults(), as this data was already in
           memory, and it had the unintended consequence of erasing any modifications
           to ship values that were set in the sysdef file, forcing a sysdef reload
           every time xtkill was used.
jimmyhua73 at**20060630092932
 	* robotd/death.c in function death(), I added newline character
 	to the reason of death on all mprintf statements "\n", so it
 	displays properly in debug mode. 
[freebsd compilation fix, missing header
quozl at**20060705062726
 	* ntserv/main.c: add signal.h include, after a report from a FreeBSD
 	user showed that my enthusiastic trimming of headers had broken
 	compilation on other operating systems.
[avoid lies to metaserver due pre-t robots
quozl at**20060703021915
 	* solicit.c: count PFBPROBOT slots as being free, since we expect them
 	to back off and quit if a player arrives, so that the metaserver report
 	of players properly excludes pre-t robots.
jimmyhua73 at**20060702153128
 This completes the fixes I started with war declarations. 
 Basically, war is declared when
 	1. t-mode starts. 
 	2. bot is forced to switch teams
 Further peace is declared when:
 	3. everytime you take out a new ship. 
 This should cover all scenarios in a typical pickup game. 
 Tested by having robots join a bronco style game. 1 Kli, 4 feds, 4 Roms.
 Check war decs. 
 Have the 1 kli get forced to join one of the t-mode teams. Check war decs
 Have Feds get timercided, and get forced to join Klis. 
 Check war decs. 
 Wait till Roms cause a genocide (Roms will take a neutral planet!). 
 Then games continues as Rom vs. Kli, and check war decs. 
 Changelog here:
 	* robotd/update_players.c changed declare_intents() function so
 	that it will return success or failure codes. Also, changed function
 	so that you may declare peace only, by doing declare_intents(1). 
 	* robotd/decide.c added static int needswardec in function decide()
 	so that robot can track when t-mode dies off and starts up again. 
 	* robotd/decide.c added in function decide() logic so, 
 	declare_intents(0) function gets called when t-mode 
 	just starts up. 
 	* robotd/decide.c modified in function decide() other calls
 	to declare_intents() so that they conform to the extra 
 	parameter passing
 	* robotd/robot.c added comment in function s_recharge() 
 	a peace request never gets called when robot orbits a 
 	planet it originally wanted to refuel from 
 	* robotd/robot.c in function find_safe_planet() fixed 
 	some buggy logic which allowed robots to head towards 
 	hostile planets to refuel/repair. 
 	* robotd/robot.c in function reset_r_info() modified 
 	call to declare_intents() to conform to newly modified
[continuum ghostbust diagnostics
quozl at**20060630025545
 	* daemonII.c (ghostmess): add reason for ghostbust to message,
 	and increase logging of normal ghostbust timeout in ERRORS.
[untabify daemon main
quozl at**20060630022904
 	* daemonII.c: removed all tabs using untabify in emacs.
[newbie robots war declarations test
quozl at**20060630020843] 
[Newbie robots now declare war properly in pickup games
quozl at**20060630011431
 	Derived from Jimmy Huang's patch of the same name.
 	* robotd/data.c: fixed comment misspelling in int delay.  delay
 	for declaring war.
 	* robotd/decide.c (decide): added some comments to help me follow
 	the code better
 	* robotd/main.c (main): fixed up indentation of variable
 	declarations. Added switchedteams variable. Modified main()
 	function so that when a team switch occurs, declare_intents() gets
 	called after choosing a new ship.
 	* robotd/robot.c (reset_r_info): added some commentary on the
 	declare_intents() call, which only gets something done only if
 	someone sends a reset command to the robot.
 	* robotd/robot.c (send_initial): removed commented code of
 	declare_intents(). This was a bug workaround, robot sends a dummy
 	packet so it doesn't get ghostbusted.  Doesn't seem needed
 	* robotd/update_players.c (declare_intents): added commentary on
 	how this function is supposed to work. Function will now properly
 	declare war on the 2 teams with the most players that isn't the
 	same team as yourself. And then declares peace with everyone else.
[continuum ban vote tweaks 2006-06
quozl at**20060622015354
 Following review of continuum recording 2006-06-07-22-00:
 - require four votes to ban instead of two, to defeat ban scumming,
 - expire ban votes within two minutes instead of ten,
 - expire eject votes within five minutes instead of ten.
[xtkill ship change fixes
williamb at**20060620005009
          * tools/xtkill.c: Adds the ability to set ship to galaxy class, removes unneccessary
            ship size change for ATT, and updates the list of valid ship types to include
            the super SC with 1 point torps (this was missing from list of valid ship types).
 M ./Vanilla/tools/xtkill.c -8 +5
jimmyhua73 at**20060616103448
 	* docs/sample_ports added observer port definitions for
 	newbie server. Added commentary to make it easier to configure
 	the port configuration for a newbie server setup. 
[Chaos mode starbase enhancements
williamb at**20060606200821
          * orbit.c, transwarp.c: Allows starbases to transwarp to and dock with other
            bases if chaos mode is activated.
[Twarp message fix
williamb at**20060606200652
          * transwarp.c: Fixes outdated reference to transwarp hours.
[ATT and invalid ship fixes
williamb at**20060603092650
       * getentry.c, main.c: allow listing of ATT on features screen, and allow player to select 
         ATT from entry window if ship is defined in sysdef as a valid ship.  Also fixes incorrect
         error message in the case of invalid ship type.
Stephen Thorne <stephen at>**20060614103104] 
jimmyhua73 at**20060614105540
 	* robotd/struct.h modify mapchars to 3 characters to hold the NULL
 	at the end
 	* robotd/enter.c initialize final character to be NULL at the end
 	when the robot first enters the game. 
jimmyhua73 at**20060613104425
         * INSTALL.Newbie updated installation documentation to reflect
         changes in code. Also, CONFIRM=0 only works, CONFIRM=2 does not
         * INSTALL.Newbie added toggle robdc, assume robots don't carry.
         Also added lookahead=0 to emulate how robots were before Trent
         fixed the torp-dir bug.
         * robotd/data.c added extern int robdc (robots don't carry)
         * robotd/data.h extern int robdc defaults to not activated.
         * robotd/data.h added compiler define NO_PFORBIT, so robot
         doesn't depend on PFORBIT flag to determine if someone is picking
         armies or not.
         * robotd/dmessage.c added robdc in help. added robdc in messaging
         * robotd/update_players.c commented out a continue; statement
         as the for loop gets exited too quickly sometimes.
         * robotd/update_players.c stale information of p->closest_pl is
         kept even when enemy becomes invisible. Will be used later.
         * robotd/update_players.c don't update last x or y if invisible.
         * robotd/update_players.c changes to check_orbit() function to
         make sure players is marked as orbiting a planet when cloaked near
         a planet, or invisible.
         * robotd/update_players.c changed some debug statements to make
         them more readable during a denemy debug session.
         * robotd/update_players.c army_check1() and army_check2() added
         logic so if robdc is activated, robot doesn't track fellow
         robot carriers.
         * robotd/update_players.c added some commentary so the army
         tracking code is more readble. Commented out a beam-down to
         friendly in favor of the more pessimistic possibility that
         the planet simply popped.
[Cross-transwarp check
williamb at**20060608223709
     * transwarp.c: Prevent transwarping to a base that is already in transwarp.
[post 2.11.1 release process notes
quozl at**20060601040643] 
[include config.guess in make dist
quozl at**20060601033548] 
[include config.sub in make dist
quozl at**20060601033011] 
[TAG 2.11.1
quozl at**20060601025406] 
Patch bundle hash:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url :