Commit graph

148 commits

Author SHA1 Message Date
d28fbbb186 Fix race in io_output() that can lead to double-free
Move call of ioq_makeiov() to its use, because calling it before
empth_select() is racy, as follows.

Player thread flushes output by calling io_output(player->iop, 1).
io_output() sets up iov[] to point to queued output.  empth_select()
blocks on output.

Another thread sends a C_FLASH or C_INFORM message to this player.
This calls io_output(p->iop, 0).  The output file descriptor has
become writable since the player thread blocked on it, so some output
gets written and dequeued.

The player thread resumes, writes out iov[] and dequeues.  Any output
already written by the other thread gets duplicated.  If the other
thread's dequeue operation freed struct io buffers, there's use after
free followed by double-free.
2010-07-25 18:24:00 +02:00
243a15052f Convert spaces to tabs 2010-06-20 18:36:44 +02:00
373651359e Coding style fixes, mostly indentation and whitespace 2010-06-20 18:36:38 +02:00
a38c47a22c Generation numbers didn't catch all potential yields on output
io_output_if_queue_long() called ef_make_stale() only for long queues.
Missed in commit 2fa5f652, v4.3.24.
2010-03-10 09:40:48 +01:00
73e25ff21e Update copyright notice 2010-01-19 08:40:17 +01:00
2fa5f65257 Generation numbers to catch write back of stale copies
Oops when a stale copy is written back, i.e. the processor was yielded
since the copy was made.  Such bugs are difficult to spot.  Sequence
numbers catch them when they do actual harm (they also catch different
bugs).  Generation numbers catch them even when they don't.

New ef_generation to count generations.  Call new ef_make_stale() to
increment it whenever the processor may be yielded.

New struct emptypedstr member generation.  To conserve space, make it
a bit-field of twelve bits, i.e. generations are only recorded modulo
2^12.  Make sure all members of unit empobj_storage share it.  It is
only used in copies; its value on disk and in the cache is
meaningless.  Copies with generation other than ef_generation are
stale.  Stale copies that are a multiple of 2^12 generations old can't
be detected, but that is sufficiently improbable.

Set generation to ef_generation by calling new ef_mark_fresh() when
making copies in ef_read() and ef_blank().  nav_ship() and
fltp_to_list() make copies without going through ef_read(), and
therefore need to call ef_mark_fresh() as well.  Also call it in
obj_changed() to make check_sect_ok() & friends freshen their argument
when it is unchanged.

New must_be_fresh() oopses when its argument is stale.  Call it in
ef_write() to catch write back of stale copies.
2010-01-19 08:36:01 +01:00
c528fcbe3e Update known contributors comments 2009-12-13 17:34:28 +01:00
c9de868d55 Change naming convention of POSIX emulation layer for Windows
Use prefix w32 instead of posix: Rename posixfile.c, posixio.c to
w32file.c, w32io.c.  Rename posix_accept(), posix_bind(),
posix_close(), posix_fd2socket(), posix_listen(), posix_mkdir(),
posix_setsockopt(), posix_shutdown(), posix_socket() to w32_accept(),
w32_bind(), w32_fd2socket(), w32_list(), w32_mkdir(),
w32_setsockopt(), w32_shutdown(), w32_socket().
2009-11-30 19:45:28 +01:00
39398997fe Include <winsock2.h> only through "sys/socket.h"
Because we need to #undef NS_ALL after <winsock2.h>, and want to do
that in just one place.
2009-11-30 19:45:27 +01:00
1c08ccf25b Revamp server's Windows POSIX compatibility code
Unlike POSIX sockets, Windows sockets are not file descriptors, but
"OS handles", with a completely separate set of functions.

However, Windows can create a file descriptor for a socket, and return
a file descriptor's underlying handle.  Use that instead of wrapping
our own file descriptors around Windows file descriptors and sockets.

Remove the wrapping machinery: MAX_FDS, enum fdmap_io_type, struct
fdmap, fdmap[], nfd, get_fd(), free_fd(), set_fd(), lookup_handle(),
lookup_fd().

Rewrite SOCKET_FUNCTION(), posix_accept(), posix_socket(),
posix_close(), ftruncate(), posix_open(), posix_read(), posix_write(),
fcntl().

Remove FILE_FUNCTION(), posix_fstat(), posix_lseek(),
SHARED_FUNCTION(), and fileno(), because the system's functions now
work fine.

posix_fsync() is used only #ifdef _WIN32, remove it, and call
_commit() directly.

The old code stuffed WSA error codes into errno, which doesn't work.
Use new w32_set_winsock_errno() to retrieve, convert & stuff into
errno.  Adapt inet_ntop() to set the WSA error code instead of errno,
so it can use w32_set_winsock_errno().

Move EWOULDBLOCK from sys/socket.h to w32misc.h, and drop unused
ENOTSOCK, EAFNOSUPPORT.

Use SOCKET rather than int in Windows-specific code.
2009-11-30 19:45:04 +01:00
2bfe7a1198 Don't log out player when update aborts a command under Windows
pthread.c's empth_select() returned 1 instead of 0 when empth_wakeup()
interrupted select().  This made io_input() attempt to read input,
which failed with WSAEWOULDBLOCK.  The failure then got propagated all
the way up, and the player got logged out.  Fix by returning 0 in that
case.
2009-11-30 19:43:47 +01:00
1b4496253d Move queue flush out of io.c
Player threads may only sleep under certain conditions.  In
particular, they must not sleep while a command is being aborted by
the update or shutdown.

io.c should not know about that.  Yet io_output_all() does, because it
needs to give up when update or shutdown interrupt it.  The function
was introduced in Empire 2, but it didn't give up then.  Fixed in
commit a7fa7dee, v4.2.22.  The fix dragged unwanted knowledge of
command abortion into io.c.

To clean up this mess, io_output_all() has to go.

First user is io_write().  io_write() automatically flushes the queue.
In wait-mode, it calls io_output_all() when the queue is longer than
the bufsize, to attempt flushing the queue completely.  In
no-wait-mode, it calls io_output() every bufsize bytes.  Except the
test for that is screwy, so it actually misses some of the flush
conditions.

The automatic flush makes io_write() differ from io_gets(), which is
ugly.  It wasn't present in BSD Empire 1.1.  Remove it again, dropping
io_write()'s last argument.

Flush the queue in its callers pr_player() and upr_player() instead.
Provide new io_output_if_queue_long() for them.  Requires new struct
iop member last_out to keep track of queue growth.  pr_player() and
upr_player() call repeatedly until it makes no more progress.  This
flushes a bit less eagerly in wait-mode, and a bit more eagerly in
non-wait mode.

Second user is recvclient().  It needs to flush the queue before
potentially sleeping in io_input().  Do that with a simple loop around
io_output().  No functional change there.
2009-07-19 14:11:53 -04:00
7fd5b86990 Indentation fix 2009-07-19 14:11:53 -04:00
d052239a7a Make empth_rwlock_t prefer writers
LWP and Windows implementations already did that.  Rewrite the
pthreads implementation.

The write-bias makes the stupid play_wrlock_wanted busy wait in
dispatch() unnecessary.  Remove it.
2009-07-19 14:11:52 -04:00
2e4f63c270 Remove IO_NOWAIT, IO_WAIT
They make the code slightly clearer in some places, and more
complicated in others.  Not worth it.
2009-07-19 14:11:52 -04:00
6f6c90d406 Make io_output() return a sane value
Return number of bytes written on success, -1 on error.  In
particular, return zero when nothing was written because the queue was
empty, or because the write slept and got woken up, or because the
write refused to sleep.

Before, it instead returned the number of bytes remaining to be
written when empth_select() failed, when woken up from sleep, or
refusing to sleep.  You couldn't tell from the return value whether
the call made progress writing out the queue.

The current callers don't actually notice the change.
2009-07-19 14:11:52 -04:00
328adc6fac Clean up bogus setting of IO_EOF in io_output()
Don't set IO_EOF when writev() returns zero.  I don't think this could
happen, but it's wrong anyway, because a short write should not stop
future reads.
2009-07-19 14:11:52 -04:00
3805548b3e Remove blocking struct iop operation
The blocking I/O option makes no sense in the server, because it
blocks the server process instead of the thread.  In fact, it's been
unused since Empire 2, except for one place, where it was used
incorrectly, and got removed in the previous commit.

Make I/O non-blocking in io_open() unconditionally.  Remove IO_NBLOCK
and io_noblocking().
2009-07-19 14:11:52 -04:00
0025f24f1e Remove long defunct IO_NEWSOCK
Chainsaw used this together with the notify callback to make the iop
data type usable for sockets it listened on, so that io_select() could
multiplex them along with the sockets used for actual I/O.
io_select() became unused in Empire 2, and finally got removed in
commit 875d72a0, v4.2.13.  That made the IO_NEWSOCK and the notify
callback defunct.  The latter got removed in commit 7d5a6b81, v4.3.1.
2009-07-19 14:11:52 -04:00
3ce0cea94c Fix race condition in empth_sleep() for Windows
Calculation of sleep duration tried to protect against integer
underflow, but the protection was racy.  Rewrite the whole thing.
2009-07-19 14:11:52 -04:00
9ee9eb3234 Fix empth_sleep() for argument in the past and pthreads
Calculation of sleep duration suffered integer underflow for unsigned
time_t and arguments in the past.  This made empth_sleep() sleep for
"a few" years instead of not at all.
2009-07-19 14:11:52 -04:00
5e132e3874 Remove useless memset() before free() 2009-04-25 10:16:27 +02:00
56e717859b Use sys/select.h for select()
Should be more portable to modern systems and could be less portable
to obsolete systems than the traditional sys/time.h sys/types.h
unistd.h incantation.
2009-04-10 19:09:58 +02:00
90f8f2b099 Don't use 0 as null pointer constant, part 2
This part replaces E != 0 by E, where E has pointer type.
2009-03-24 21:46:01 +01:00
615681ce16 Don't use 0 as null pointer constant, part 1
Use NULL instead of 0, for clarity.  Except in pointer comparisons;
leave that to the next two commits.
2009-03-24 21:45:44 +01:00
eea9e76bf8 Don't log out player when update aborts a command with pthreads
pthread.c's empth_select() returned -1 when empth_wakeup() interrupted
select().  The failure then got propagated all the way up, and the
player got logged out.  Fix by returning 0 in that case.  While there,
retry on EINTR, to match LWP.  Also clarify comments.
2009-03-01 13:04:48 +01:00
5073b022fd Remove unused empth_terminate()
Unused since 4.3.10.  Can be used safely only in very special
circumstances.

Removal allows simplifying pthread.c and ntthread.c some.  liblwp left
alone.
2009-03-01 10:49:48 +01:00
ee20a9cd34 Update known contributors comments 2009-02-18 21:11:33 +01:00
35ef345ecb Update copyright notice 2009-02-08 09:33:18 +01:00
48cec49fbf Fix empth_select() for funny flag arguments
EMPTH_POSIX and EMPTH_W32 implementations rejected values other than a
single flag.  Such values aren't used now, but it violates the
contract all the same.
2009-02-02 08:08:38 +01:00
6144a363d6 Fix pthread's empth_select() not to change the timeout
Commit 08b94556 introduced the timeout parameter.  The empthread
implementation could change it, at least on some systems, and its user
worked around a possible change.  However, that behavior was not
documented, and it's inconvenient.  Fix the pthread implementation,
and remove the workaround.
2009-02-01 18:06:09 +01:00
Ron Koenderink
08b9455682 Reimplement max_idle without a separate thread
Remove the KillIdle thread.  Add timeout to struct iop, initialized in
io_open().  Obey it in io_input() by passing it to empth_select().  If
empth_select() times out, report that back through io_input() to
recvclient() and player_login().  If player_login() receives a timeout
indication, print a message and terminate the session.  If
recvclient() receives a timeout indication, flash a message to the
player and initiate a shut down the player's session.

Create WIN32 sys/time.h to define struct timeval.  This creates some
conflicts with WIN32 windows.h definitions.  Including windows.h in
show.c and info.c creates conflicts, so remove that.  Modify service.c
to include sys/socket.h instead of windows.h to remove the conflict
with sys/time.h.
2009-02-01 17:06:33 +01:00
d702068457 Fix trailing whitespace 2008-09-17 21:31:40 -04:00
Ron Koenderink
74b655f9fa Allow any length RW lock names for WIN32
Dynamically allocate the string space for RW
lock names for WIN32 (ntthread.c).  This
makes the WIN32 more consistent with the other
environments.
2008-09-13 16:39:45 -06:00
Ron Koenderink
838a1010c2 Allow any length thread names for WIN32
Dynamically allocate the string space for thread
name in WIN32 (ntthread.c) thread space.  This
makes the WIN32 more consistent with the other
environments.  It also addresses WIN32 issue of
the print width of 17 being used and only having
space for 16 characters in the fixed allocation.
2008-09-13 15:29:42 -06:00
0900cca4f5 Fix commit d46b0b72 (didn't even compile with pthreads) 2008-09-12 18:05:58 -04:00
Ron Koenderink
4d7d7bb77e Add missing error check for thread creation for WIN32
_beginthread() call in empth_create() has two error
return values 0L and 1L.  Add the missing check for 0L.
2008-09-12 07:22:28 -06:00
Ron Koenderink
af2a87e490 Ensure the empth_sleep() always yields for WIN32
The WIN32 version did not block when the sleep was
already reached by the time empth_sleep() did the
time remaining calculation.  The other versions
of empth_sleep() do always yield.
2008-09-12 07:22:28 -06:00
d46b0b727d Make empth_name() and empth_set_name() take a thread argument 2008-09-11 19:25:34 -04:00
Ron Koenderink
2ddeda99d0 New empth_name() and empth_set_name() 2008-09-11 14:46:31 -06:00
ed9da7cf06 Update known contributors comments 2008-08-03 08:04:08 -04:00
1d9aac2cf9 Add gcc attribute format where it's missing 2008-08-02 12:00:33 -04:00
Ron Koenderink
9a4f49f128 Add missing thread yield system call.
This change fixes a bug where the threads were not treated
fairly.  Before the fix, empth_yield would only yield to
threads already waiting hThreadMutex mutex.  It would not
yield to other threads ready to run from the release of other
mutexes.  An example of this is that the update task did
not start when force command was issued from script sequence.
2008-03-27 20:07:11 -06:00
77e95bd788 Clean up library dependencies
Move stuff to untangle the ugly cyclic dependencies between the
archives built for selected subdirectories of src/lib/:

* Move common/io.c to empthread/ because it requires empthread stuff

* Move parts of subs/nstr.c to common/nstreval.c to satisfy
  common/ef_verify.o

* Move getstarg.c getstring.c onearg.c from gen/ to subs/ because they
  require stuff from there

* Move bridgefall.c check.c damage.c empobj.c journal.c maps.c
  sectdamage.c from common/ to subs/ because they require stuff from
  there

* Move cnumb.c from subs/ to common/ to satisfy common/type.o

* Move log.c fsize.c from common/ to gen/ because they really belong
  there

* Move emp_config.c mapdist.c from gen/ to common/ because they really
  belong there, and require stuff from libglobal.a

Also package as/ as libas.a to satisfy common/path.o.

Remaining dependencies:

    lib             needs
    --------------------------------------------
    libas.a         libglobal.a
    libcommon.a     libas.a libglobal.a libgen.a
    libgen.a
    libglobal.a
    liblwp.a        libgen.a
    libw32.a[*]     libgen.a

    [*] Except for service.o, which can only be linked into the server

Link order now: liblwp.a libcommon.a libas.a libgen.a libglobal.a
libw32.a.  The position of libw32.a is not quite right, but works
anyway.
2008-02-03 08:11:13 +01:00
db02dda32f Update copyright notice 2008-01-19 10:15:37 +01:00
Ron Koenderink
90a53439b2 (loc_Exit_Handler, empth_init) [_WIN32]: Correct the function declaration
for loc_Exit_Handler().  Remove unnecessary cast.
2007-11-27 03:29:35 +00:00
Ron Koenderink
c115ed1327 (random, srandom) [_WIN32]: Provide random and srandom
POSIX equivalents instead of using the WIN32 rand/srand functions.
The files were derived from GNU libc source.

(empth_threadMain) [_WIN32]: Remove the srandom() as the
POSIX equivalent are not thread specific as the WIN32 functions were.
2007-10-21 15:34:27 +00:00
Ron Koenderink
0627deae05 (empth_sleep) [_WIN32]: Remove a change to the random seeding
that accidently got committed in rev 1.65.  Was incorrect in rev 1.66.

(empth_sleep) [_WIN32]: Switch srand() to srandom() to be consistent
with the rest of the empire code.
2007-10-20 12:59:49 +00:00
Ron Koenderink
f449c3f8a4 (empth_sleep) [_WIN32]: Remove a change to the random seeding
that accidently got committed in rev 1.65.
2007-10-20 12:15:45 +00:00
Ron Koenderink
274c3d3a36 (empth_sleep) [_WIN32]: Ensure the thread does not waking up early.
It has been seen which caused an update to be missed.
2007-10-20 11:51:50 +00:00