You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-04-13 14:42:51 -07:00
Rebase against upstream changes.
This commit is contained in:
@@ -1,19 +1,18 @@
|
||||
From f116e9e73f00bd6c65ebd087a1f7b23ceb9064a9 Mon Sep 17 00:00:00 2001
|
||||
From f478d1b97efc4fe63f8ccc01a2ab214c0bffc579 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 12:25:23 +1100
|
||||
Subject: server: Implement remaining wineserver calls for job objects.
|
||||
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 6 +---
|
||||
dlls/ntdll/sync.c | 76 +++++++++++++++++++++++++++++++++++++++----
|
||||
include/winnt.h | 4 +++
|
||||
server/process.c | 59 +++++++++++++++++++++++++++++++++
|
||||
dlls/kernel32/tests/process.c | 2 --
|
||||
dlls/ntdll/sync.c | 29 +++++++++++++++++++++++++----
|
||||
server/process.c | 40 +++++++++++++++++++++++++++++++++++++++-
|
||||
server/process.h | 1 +
|
||||
server/protocol.def | 14 ++++++++
|
||||
6 files changed, 149 insertions(+), 11 deletions(-)
|
||||
server/protocol.def | 7 +++++++
|
||||
5 files changed, 72 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 1add23d..8c9a6ef 100644
|
||||
index 44e81ba..a86e331 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2269,13 +2269,11 @@ static void test_TerminateJobObject(void)
|
||||
@@ -30,34 +29,8 @@ index 1add23d..8c9a6ef 100644
|
||||
ok(dwret == 123 || broken(dwret == 0) /* randomly fails on Win 2000 / XP */,
|
||||
"wrong exitcode %u\n", dwret);
|
||||
|
||||
@@ -2401,6 +2399,7 @@ static void test_CompletionPort(void)
|
||||
port_info.CompletionKey = job;
|
||||
port_info.CompletionPort = port;
|
||||
ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
|
||||
+ todo_wine
|
||||
ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
|
||||
create_process("wait", &pi);
|
||||
@@ -2498,7 +2497,6 @@ static void test_jobInheritance(HANDLE job)
|
||||
out = FALSE;
|
||||
ret = pIsProcessInJob(pi.hProcess, job, &out);
|
||||
ok(ret, "IsProcessInJob error %u\n", GetLastError());
|
||||
- todo_wine
|
||||
ok(out, "IsProcessInJob returned out=%u\n", out);
|
||||
|
||||
dwret = WaitForSingleObject(pi.hProcess, 1000);
|
||||
@@ -2526,9 +2524,7 @@ static void test_BreakawayOk(HANDLE job)
|
||||
snprintf(buffer, MAX_PATH, "\"%s\" tests/process.c %s", selfname, "exit");
|
||||
|
||||
ret = CreateProcessA(NULL, buffer, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, &pi);
|
||||
- todo_wine
|
||||
ok(!ret, "CreateProcessA expected failure\n");
|
||||
- todo_wine
|
||||
expect_eq_d(ERROR_ACCESS_DENIED, GetLastError());
|
||||
|
||||
if (ret)
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index ce1a635..e001e28 100644
|
||||
index a4df88a..400aa7d 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -56,6 +56,7 @@
|
||||
@@ -110,77 +83,8 @@ index ce1a635..e001e28 100644
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -634,8 +655,51 @@ NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS c
|
||||
*/
|
||||
NTSTATUS WINAPI NtSetInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info, ULONG len )
|
||||
{
|
||||
- FIXME( "stub: %p %u %p %u\n", handle, class, info, len );
|
||||
- return STATUS_SUCCESS;
|
||||
+ JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit;
|
||||
+ NTSTATUS status = STATUS_SUCCESS;
|
||||
+
|
||||
+ TRACE( "(%p, %u, %p, %u)\n", handle, class, info, len );
|
||||
+
|
||||
+ if (class >= MaxJobObjectInfoClass)
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ switch (class)
|
||||
+ {
|
||||
+
|
||||
+ case JobObjectExtendedLimitInformation:
|
||||
+ if (len != sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ basic_limit = &(((JOBOBJECT_EXTENDED_LIMIT_INFORMATION *)info)->BasicLimitInformation);
|
||||
+ if (basic_limit->LimitFlags & ~JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS)
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ goto set_basic_limits;
|
||||
+
|
||||
+ case JobObjectBasicLimitInformation:
|
||||
+ if (len != sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION))
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ basic_limit = info;
|
||||
+ if (basic_limit->LimitFlags & ~JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS)
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ set_basic_limits:
|
||||
+ SERVER_START_REQ( set_job_limits )
|
||||
+ {
|
||||
+ req->handle = wine_server_obj_handle( handle );
|
||||
+ req->limit_flags = basic_limit->LimitFlags;
|
||||
+ status = wine_server_call( req );
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ FIXME( "stub: %p %u %p %u\n", handle, class, info, len );
|
||||
+ return STATUS_NOT_IMPLEMENTED;
|
||||
+ }
|
||||
+
|
||||
+ return status;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
diff --git a/include/winnt.h b/include/winnt.h
|
||||
index 4b06b2c..c2aa50e 100644
|
||||
--- a/include/winnt.h
|
||||
+++ b/include/winnt.h
|
||||
@@ -5610,6 +5610,10 @@ typedef struct _JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
|
||||
#define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x00002000
|
||||
#define JOB_OBJECT_LIMIT_SUBSET_AFFINITY 0x00004000
|
||||
|
||||
+#define JOB_OBJECT_LIMIT_VALID_FLAGS 0x0007ffff
|
||||
+#define JOB_OBJECT_BASIC_LIMIT_VALID_FLAGS 0x000000ff
|
||||
+#define JOB_OBJECT_EXTENDED_LIMIT_VALID_FLAGS 0x00007fff
|
||||
+
|
||||
typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP
|
||||
{
|
||||
RelationProcessorCore = 0,
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index f9738c0..a1ab8c7 100644
|
||||
index 5821435..727a682 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -65,6 +65,7 @@ static unsigned int process_map_access( struct object *obj, unsigned int access
|
||||
@@ -191,36 +95,40 @@ index f9738c0..a1ab8c7 100644
|
||||
|
||||
static const struct object_ops process_ops =
|
||||
{
|
||||
@@ -147,6 +148,7 @@ struct job
|
||||
struct object obj; /* object header */
|
||||
@@ -148,6 +149,7 @@ struct job
|
||||
struct list process_list; /* list of all processes */
|
||||
int num_processes; /* count of running processes */
|
||||
+ int limit_flags; /* limit flags */
|
||||
unsigned int limit_flags; /* limit flags */
|
||||
+ int terminating; /* job is terminating */
|
||||
struct completion *completion_port; /* associated completion port */
|
||||
apc_param_t completion_key; /* key to send with completion messages */
|
||||
};
|
||||
|
||||
static const struct object_ops job_ops =
|
||||
@@ -185,6 +187,7 @@ static struct job *create_job_object( struct directory *root, const struct unico
|
||||
SACL_SECURITY_INFORMATION );
|
||||
@@ -189,6 +191,7 @@ static struct job *create_job_object( struct directory *root, const struct unico
|
||||
list_init( &job->process_list );
|
||||
job->num_processes = 0;
|
||||
+ job->limit_flags = 0;
|
||||
job->limit_flags = 0;
|
||||
+ job->terminating = 0;
|
||||
job->completion_port = NULL;
|
||||
job->completion_key = 0;
|
||||
}
|
||||
}
|
||||
return job;
|
||||
@@ -223,6 +226,7 @@ static void add_job_process( struct job *job, struct process *process )
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
return;
|
||||
}
|
||||
+
|
||||
process->job = (struct job *)grab_object( job );
|
||||
list_add_tail( &job->process_list, &process->job_entry );
|
||||
job->num_processes++;
|
||||
@@ -239,6 +243,23 @@ static void release_job_process( struct process *process )
|
||||
@@ -252,12 +255,36 @@ static void release_job_process( struct process *process )
|
||||
assert( job->num_processes );
|
||||
job->num_processes--;
|
||||
|
||||
- add_job_completion( job, JOB_OBJECT_MSG_EXIT_PROCESS, get_process_id(process) );
|
||||
+ if (!job->terminating)
|
||||
+ add_job_completion( job, JOB_OBJECT_MSG_EXIT_PROCESS, get_process_id(process) );
|
||||
|
||||
if (!job->num_processes)
|
||||
add_job_completion( job, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, 0 );
|
||||
}
|
||||
|
||||
+static void terminate_job( struct job *job, int exit_code )
|
||||
+{
|
||||
+ /* Windows doesn't report completion events for processes
|
||||
+ * terminated by TerminateProcess, we do the same */
|
||||
+ job->terminating = 1;
|
||||
+
|
||||
+ for (;;) /* restart from the beginning of the list every time */
|
||||
+ {
|
||||
+ struct process *process;
|
||||
@@ -234,67 +142,31 @@ index f9738c0..a1ab8c7 100644
|
||||
+ assert( process->job == job );
|
||||
+ terminate_process( process, NULL, exit_code );
|
||||
+ }
|
||||
+
|
||||
+ job->terminating = 0;
|
||||
+}
|
||||
+
|
||||
static void job_destroy( struct object *obj )
|
||||
{
|
||||
struct job *job = (struct job *)obj;
|
||||
@@ -1087,6 +1108,14 @@ DECL_HANDLER(new_process)
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (parent->job && (req->create_flags & CREATE_BREAKAWAY_FROM_JOB) &&
|
||||
+ !(parent->job->limit_flags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
|
||||
+ {
|
||||
+ set_error( STATUS_ACCESS_DENIED );
|
||||
+ close( socket_fd );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (!req->info_size) /* create an orphaned process */
|
||||
{
|
||||
create_process( socket_fd, NULL, 0 );
|
||||
@@ -1157,6 +1186,12 @@ DECL_HANDLER(new_process)
|
||||
&& !(req->create_flags & DEBUG_ONLY_THIS_PROCESS);
|
||||
process->startup_info = (struct startup_info *)grab_object( info );
|
||||
|
||||
+ if (parent->job && !((req->create_flags & CREATE_BREAKAWAY_FROM_JOB) ||
|
||||
+ (parent->job->limit_flags & JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
|
||||
+ {
|
||||
+ add_job_process( parent->job, process );
|
||||
+ }
|
||||
+
|
||||
/* connect to the window station */
|
||||
connect_process_winstation( process, current );
|
||||
|
||||
@@ -1559,3 +1594,27 @@ DECL_HANDLER(process_in_job)
|
||||
}
|
||||
@@ -1596,6 +1623,17 @@ DECL_HANDLER(process_in_job)
|
||||
release_object( process );
|
||||
}
|
||||
+
|
||||
|
||||
+/* terminate all processes associated with the job */
|
||||
+DECL_HANDLER(terminate_job)
|
||||
+{
|
||||
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_TERMINATE );
|
||||
+
|
||||
+ if (job)
|
||||
+ {
|
||||
+ terminate_job( job, req->status );
|
||||
+ release_object( job );
|
||||
+ }
|
||||
+ if (!job) return;
|
||||
+
|
||||
+ terminate_job( job, req->status );
|
||||
+ release_object( job );
|
||||
+}
|
||||
+
|
||||
+/* update limits of the job object */
|
||||
+DECL_HANDLER(set_job_limits)
|
||||
+{
|
||||
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES );
|
||||
+
|
||||
+ if (job)
|
||||
+ {
|
||||
+ job->limit_flags = req->limit_flags;
|
||||
+ release_object( job );
|
||||
+ }
|
||||
+}
|
||||
/* update limits of the job object */
|
||||
DECL_HANDLER(set_job_limits)
|
||||
{
|
||||
diff --git a/server/process.h b/server/process.h
|
||||
index 0cf9514..ae83b0e 100644
|
||||
--- a/server/process.h
|
||||
@@ -308,15 +180,13 @@ index 0cf9514..ae83b0e 100644
|
||||
/* process startup state */
|
||||
enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index b85adca..0077aa4 100644
|
||||
index 9199c7f..5ecc8d5 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3528,3 +3528,17 @@ enum coords_relative
|
||||
obj_handle_t job; /* handle to the job */
|
||||
obj_handle_t process; /* handle to the process */
|
||||
@@ -3530,6 +3530,13 @@ enum coords_relative
|
||||
@END
|
||||
+
|
||||
+
|
||||
|
||||
|
||||
+/* Terminate all processes associated with the job */
|
||||
+@REQ(terminate_job)
|
||||
+ obj_handle_t handle; /* handle to the job */
|
||||
@@ -324,11 +194,9 @@ index b85adca..0077aa4 100644
|
||||
+@END
|
||||
+
|
||||
+
|
||||
+/* Update limits of the job object */
|
||||
+@REQ(set_job_limits)
|
||||
+ obj_handle_t handle; /* handle to the job */
|
||||
+ unsigned int limit_flags; /* limit flags */
|
||||
+@END
|
||||
/* Set limit flags on a job */
|
||||
@REQ(set_job_limits)
|
||||
obj_handle_t handle; /* handle to the job */
|
||||
--
|
||||
2.3.3
|
||||
|
||||
|
@@ -1,196 +0,0 @@
|
||||
From 3babb8a2681bd530008b0d268cde0b5788177097 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 13:02:36 +1100
|
||||
Subject: server: Implement completion messages for job objects.
|
||||
|
||||
Fixes Wine bug #33723.
|
||||
|
||||
Various cleanups to fit with the rest of the wineserver
|
||||
coding style by Sebastian Lackner <sebastian@fds-team.de>.
|
||||
---
|
||||
dlls/kernel32/tests/process.c | 4 ----
|
||||
dlls/ntdll/sync.c | 15 +++++++++++++++
|
||||
server/process.c | 45 +++++++++++++++++++++++++++++++++++++++++++
|
||||
server/protocol.def | 8 ++++++++
|
||||
4 files changed, 68 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 8c9a6ef..a86e331 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2399,7 +2399,6 @@ static void test_CompletionPort(void)
|
||||
port_info.CompletionKey = job;
|
||||
port_info.CompletionPort = port;
|
||||
ret = pSetInformationJobObject(job, JobObjectAssociateCompletionPortInformation, &port_info, sizeof(port_info));
|
||||
- todo_wine
|
||||
ok(ret, "SetInformationJobObject error %u\n", GetLastError());
|
||||
|
||||
create_process("wait", &pi);
|
||||
@@ -2407,16 +2406,13 @@ static void test_CompletionPort(void)
|
||||
ret = pAssignProcessToJobObject(job, pi.hProcess);
|
||||
ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
|
||||
|
||||
- todo_wine
|
||||
test_completion(port, JOB_OBJECT_MSG_NEW_PROCESS, (DWORD_PTR)job, pi.dwProcessId, 0);
|
||||
|
||||
TerminateProcess(pi.hProcess, 0);
|
||||
dwret = WaitForSingleObject(pi.hProcess, 1000);
|
||||
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
|
||||
- todo_wine
|
||||
test_completion(port, JOB_OBJECT_MSG_EXIT_PROCESS, (DWORD_PTR)job, pi.dwProcessId, 0);
|
||||
- todo_wine
|
||||
test_completion(port, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, (DWORD_PTR)job, 0, 100);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index e001e28..87ff3e0 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -694,6 +694,21 @@ NTSTATUS WINAPI NtSetInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS cla
|
||||
SERVER_END_REQ;
|
||||
break;
|
||||
|
||||
+ case JobObjectAssociateCompletionPortInformation:
|
||||
+ if (len != sizeof(JOBOBJECT_ASSOCIATE_COMPLETION_PORT))
|
||||
+ return STATUS_INVALID_PARAMETER;
|
||||
+
|
||||
+ SERVER_START_REQ( set_job_completion )
|
||||
+ {
|
||||
+ JOBOBJECT_ASSOCIATE_COMPLETION_PORT *port_info = info;
|
||||
+ req->handle = wine_server_obj_handle( handle );
|
||||
+ req->port = wine_server_obj_handle( port_info->CompletionPort );
|
||||
+ req->key = wine_server_client_ptr( port_info->CompletionKey );
|
||||
+ status = wine_server_call(req);
|
||||
+ }
|
||||
+ SERVER_END_REQ;
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
FIXME( "stub: %p %u %p %u\n", handle, class, info, len );
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index a1ab8c7..10193ef 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -149,6 +149,9 @@ struct job
|
||||
struct list process_list; /* list of all processes */
|
||||
int num_processes; /* count of running processes */
|
||||
int limit_flags; /* limit flags */
|
||||
+ int terminating; /* job is terminating */
|
||||
+ struct completion *completion_port;
|
||||
+ apc_param_t completion_key;
|
||||
};
|
||||
|
||||
static const struct object_ops job_ops =
|
||||
@@ -188,6 +191,9 @@ static struct job *create_job_object( struct directory *root, const struct unico
|
||||
list_init( &job->process_list );
|
||||
job->num_processes = 0;
|
||||
job->limit_flags = 0;
|
||||
+ job->terminating = 0;
|
||||
+ job->completion_port = NULL;
|
||||
+ job->completion_key = 0;
|
||||
}
|
||||
}
|
||||
return job;
|
||||
@@ -214,6 +220,12 @@ static unsigned int job_map_access( struct object *obj, unsigned int access )
|
||||
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
|
||||
}
|
||||
|
||||
+static void add_job_completion( struct job *job, apc_param_t msg, apc_param_t pid )
|
||||
+{
|
||||
+ if (job->completion_port)
|
||||
+ add_completion(job->completion_port, job->completion_key, pid, STATUS_SUCCESS, msg);
|
||||
+}
|
||||
+
|
||||
static void add_job_process( struct job *job, struct process *process )
|
||||
{
|
||||
if (!process->running_threads)
|
||||
@@ -230,6 +242,8 @@ static void add_job_process( struct job *job, struct process *process )
|
||||
process->job = (struct job *)grab_object( job );
|
||||
list_add_tail( &job->process_list, &process->job_entry );
|
||||
job->num_processes++;
|
||||
+
|
||||
+ add_job_completion( job, JOB_OBJECT_MSG_NEW_PROCESS, get_process_id(process) );
|
||||
}
|
||||
|
||||
/* called when a process has terminated, allow one additional process */
|
||||
@@ -241,10 +255,20 @@ static void release_job_process( struct process *process )
|
||||
|
||||
assert( job->num_processes );
|
||||
job->num_processes--;
|
||||
+
|
||||
+ if (!job->terminating)
|
||||
+ add_job_completion( job, JOB_OBJECT_MSG_EXIT_PROCESS, get_process_id(process) );
|
||||
+
|
||||
+ if (!job->num_processes)
|
||||
+ add_job_completion( job, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, 0 );
|
||||
}
|
||||
|
||||
static void terminate_job( struct job *job, int exit_code )
|
||||
{
|
||||
+ /* Windows doesn't report completion events for processes
|
||||
+ * terminated by TerminateProcess, we do the same */
|
||||
+ job->terminating = 1;
|
||||
+
|
||||
for (;;) /* restart from the beginning of the list every time */
|
||||
{
|
||||
struct process *process;
|
||||
@@ -258,6 +282,8 @@ static void terminate_job( struct job *job, int exit_code )
|
||||
assert( process->job == job );
|
||||
terminate_process( process, NULL, exit_code );
|
||||
}
|
||||
+
|
||||
+ job->terminating = 0;
|
||||
}
|
||||
|
||||
static void job_destroy( struct object *obj )
|
||||
@@ -267,6 +293,9 @@ static void job_destroy( struct object *obj )
|
||||
|
||||
assert( !job->num_processes );
|
||||
assert( list_empty(&job->process_list) );
|
||||
+
|
||||
+ if (job->completion_port)
|
||||
+ release_object(job->completion_port);
|
||||
}
|
||||
|
||||
static void job_dump( struct object *obj, int verbose )
|
||||
@@ -1618,3 +1647,19 @@ DECL_HANDLER(set_job_limits)
|
||||
release_object( job );
|
||||
}
|
||||
}
|
||||
+
|
||||
+DECL_HANDLER(set_job_completion)
|
||||
+{
|
||||
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES );
|
||||
+
|
||||
+ if (job)
|
||||
+ {
|
||||
+ if (!job->completion_port)
|
||||
+ {
|
||||
+ job->completion_port = get_completion_obj( current->process, req->port, IO_COMPLETION_MODIFY_STATE );
|
||||
+ job->completion_key = req->key;
|
||||
+ }
|
||||
+ else set_error( STATUS_INVALID_PARAMETER );
|
||||
+ release_object( job );
|
||||
+ }
|
||||
+}
|
||||
diff --git a/server/protocol.def b/server/protocol.def
|
||||
index 0077aa4..c88c970 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -3542,3 +3542,11 @@ enum coords_relative
|
||||
obj_handle_t handle; /* handle to the job */
|
||||
unsigned int limit_flags; /* limit flags */
|
||||
@END
|
||||
+
|
||||
+
|
||||
+/* Set a job completion port/key */
|
||||
+@REQ(set_job_completion)
|
||||
+ obj_handle_t handle; /* handle to the job */
|
||||
+ obj_handle_t port; /* completion port */
|
||||
+ client_ptr_t key; /* completion key */
|
||||
+@END
|
||||
--
|
||||
2.3.3
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 2885683ee26ca39acc9158c804b5287da43585ac Mon Sep 17 00:00:00 2001
|
||||
From 6e6cd9108a8f3c0b9d158ac2605e9b0a08b19c71 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Lackner <sebastian@fds-team.de>
|
||||
Date: Sat, 28 Feb 2015 06:58:48 +0100
|
||||
Subject: server: Implement waiting for job objects.
|
||||
@@ -29,16 +29,16 @@ index aaa1a6e..c325d32 100644
|
||||
return;
|
||||
}
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index 89c029e..8c654b4 100644
|
||||
index 3ff0be5..f59fe2b 100644
|
||||
--- a/server/process.c
|
||||
+++ b/server/process.c
|
||||
@@ -151,6 +151,7 @@ struct job
|
||||
int num_processes; /* count of running processes */
|
||||
int limit_flags; /* limit flags */
|
||||
unsigned int limit_flags; /* limit flags */
|
||||
int terminating; /* job is terminating */
|
||||
+ int signaled; /* job is signaled */
|
||||
struct completion *completion_port;
|
||||
apc_param_t completion_key;
|
||||
struct completion *completion_port; /* associated completion port */
|
||||
apc_param_t completion_key; /* key to send with completion messages */
|
||||
};
|
||||
@@ -193,6 +194,7 @@ static struct job *create_job_object( struct directory *root, const struct unico
|
||||
job->num_processes = 0;
|
||||
@@ -48,7 +48,7 @@ index 89c029e..8c654b4 100644
|
||||
job->completion_port = NULL;
|
||||
job->completion_key = 0;
|
||||
}
|
||||
@@ -285,6 +287,8 @@ static void terminate_job( struct job *job, int exit_code )
|
||||
@@ -284,6 +286,8 @@ static void terminate_job( struct job *job, int exit_code )
|
||||
}
|
||||
|
||||
job->terminating = 0;
|
||||
@@ -57,7 +57,7 @@ index 89c029e..8c654b4 100644
|
||||
}
|
||||
|
||||
static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
|
||||
@@ -322,7 +326,8 @@ static void job_dump( struct object *obj, int verbose )
|
||||
@@ -320,7 +324,8 @@ static void job_dump( struct object *obj, int verbose )
|
||||
|
||||
static int job_signaled( struct object *obj, struct wait_queue_entry *entry )
|
||||
{
|
Reference in New Issue
Block a user