[Bug 904] New: - Solaris: Add threading support

wine-bugs at winehq.com wine-bugs at winehq.com
Sun Jul 21 16:17:15 CDT 2002


http://bugs.winehq.com/show_bug.cgi?id=904

           Summary: Solaris: Add threading support
           Product: Wine
           Version: CVS
          Platform: PC
        OS/Version: Solaris
            Status: NEW
          Severity: normal
          Priority: P2
         Component: wine-ports
        AssignedTo: wine-bugs at winehq.com
        ReportedBy: fgouget at codeweavers.com


Threading does not work correctly on Solaris (an issue for both x86 and Sparc
platforms). The reason is that Linux (and FreeBSD) treat threads differently
from Solaris.

 * on Linux a process can contain multiple threads and each thread gets a unique
system-wide identifier which is confusingly called a pid (process id). It can be
argued that Linux does not in fact have the notion of what a process is: there
is no object that represents the process that contains all these threads. So you
cannot kill a process, you can only kill its individual threads. This is because
you can only send signals to specific threads so that when you 'kill -9 pid',
you only kill one individual thread in the process.

 * on Solaris too a process can contain multiple threads (called lightweight
processes or lwp for short). However, processes and threads are each separate
system objects. When you send a signal it is sent to the process: 'kill -9 pid'
will kill the process and all its threads. Also, individual lwps do not have a
globally unique identifier. Instead their ids (typically 0, 1, 2, etc.) are only
unique within a process. So if you want to refer to a specific lwp in the system
you must use specify both the pid and the lwpid.

Wine and in particular the Wine server, need the following functionality:
1. uniquely identify a thread in the system
2. sending a signal to a specific thread
3. precisely identifying a thread's parent thread
   (for handle inheritance when creating a new process, etc. It is a
prerequisite for the debugger too)

See the following files for reference:
 * server/process.c server/process.h
   Where the wineserver keeps track of Windows processes
 * server/thread.c server/thread.h
   Where the wineserver keeps track of Windows threads
 * scheduler/client.c
   Called by a new Windows thread to register itself
 * scheduler/process.c
   Called by a new Windows process to register itself
 * include/wine/server_protocol.h
   Defines the structures used for the wineserver protocol

Then, to identify a thread uniquely we can:
 * add a unix_pid field to the 'struct process' in server/process.h
 * rename the 'unix_pid' field in 'struct thread' to 'unix_tid' in
server/thread.h
 * on Linux,   set unix_pid=0        and unix_tid=getpid()
 * on Solaris, set unix_pid=getpid() and unix_tid=_lwp_self()
 * make sure we do not write code that would identify a process by its unix_pid
   (would be a tempting thing to do on Solaris but does not work on Linux)
 * use both unix_pid and unix_tid whenever we need to identify a thread (i.e.
find its struct thread structure)

To send a signal to a specific thread, the solution is to use the procfs:
Open /proc/<pid>/lwp</lwpid>/lwpctl and write two ints: PCKILL followed by the
signal id. Do a man -s 4 proc or find it online at:
   http://www.cs.princeton.edu/cgi-bin/man2html?proc:4

Identifying a thread's parent is harder because there is no lwp_getppid()
function. So I propose the following trick:
 * just before creating a new process (in fork_and_exec), set the
WINE_PARENT_LWPID environment variable to "pid:lwpid"
 * during the process initialization check for the WINE_PARENT_LWPID environment
variable and reset it right after use
 * if set, make sure that the pid matches our ppid. If so, then the information
it contains is valid and the lwpid is the id of our parent lwp
   (which means wrapper scripts must _exec_ wine)
 * if the pid does not match our ppid, then this is a stale environment
variable: a Wine process must have started a Unix process, which in turn
launched another Wine process. But the Unix process is our parent, not the Wine
process so there are no handles to inherit anyway.
 * if the variable is not set, then this Wine process was started from Unix so
there is nothing to inherit

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://bugs.winehq.com/show_bug.cgi?id=904>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.



More information about the wine-bugs mailing list