Rebase against upstream changes.

This commit is contained in:
Sebastian Lackner
2015-04-07 20:01:32 +02:00
parent d28a7ba29e
commit c5bbea55d2
23 changed files with 278 additions and 1113 deletions

View File

@@ -1,4 +1,4 @@
From e70c80c4f78ac6306629d79f86d8c1c5439aaa17 Mon Sep 17 00:00:00 2001
From 23d528b7e744e69fa5d857be20f188ce5510c088 Mon Sep 17 00:00:00 2001
From: Andrew Cook <ariscop@gmail.com>
Date: Thu, 26 Feb 2015 13:10:41 +1100
Subject: server: Implement JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
@@ -9,10 +9,10 @@ Subject: server: Implement JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE.
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index a86e331..4f51cea 100644
index c63d6b1..5e04836 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2449,7 +2449,6 @@ static void test_KillOnJobClose(void)
@@ -2435,7 +2435,6 @@ static void test_KillOnJobClose(void)
CloseHandle(job);
dwret = WaitForSingleObject(pi.hProcess, 1000);
@@ -21,10 +21,10 @@ index a86e331..4f51cea 100644
if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
diff --git a/server/process.c b/server/process.c
index 10193ef..89c029e 100644
index 569a8fe..38bd977 100644
--- a/server/process.c
+++ b/server/process.c
@@ -141,6 +141,7 @@ static void job_dump( struct object *obj, int verbose );
@@ -140,6 +140,7 @@ static void job_dump( struct object *obj, int verbose );
static struct object_type *job_get_type( struct object *obj );
static int job_signaled( struct object *obj, struct wait_queue_entry *entry );
static unsigned int job_map_access( struct object *obj, unsigned int access );
@@ -41,8 +41,8 @@ index 10193ef..89c029e 100644
job_destroy /* destroy */
};
@@ -286,6 +287,20 @@ static void terminate_job( struct job *job, int exit_code )
job->terminating = 0;
@@ -287,6 +288,20 @@ static void terminate_job( struct job *job, int exit_code )
wake_up( &job->obj, 0 );
}
+static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
@@ -63,5 +63,5 @@ index 10193ef..89c029e 100644
{
struct job *job = (struct job *)obj;
--
2.3.3
2.3.5

View File

@@ -1,202 +0,0 @@
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 | 2 --
dlls/ntdll/sync.c | 29 +++++++++++++++++++++++++----
server/process.c | 40 +++++++++++++++++++++++++++++++++++++++-
server/process.h | 1 +
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 44e81ba..a86e331 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2269,13 +2269,11 @@ static void test_TerminateJobObject(void)
ok(ret, "TerminateJobObject error %u\n", GetLastError());
dwret = WaitForSingleObject(pi.hProcess, 1000);
- todo_wine
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
if (dwret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0);
ret = GetExitCodeProcess(pi.hProcess, &dwret);
ok(ret, "GetExitCodeProcess error %u\n", GetLastError());
- todo_wine
ok(dwret == 123 || broken(dwret == 0) /* randomly fails on Win 2000 / XP */,
"wrong exitcode %u\n", dwret);
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index a4df88a..400aa7d 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -56,6 +56,7 @@
#include "wine/server.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
+#include "winnt.h"
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -613,8 +614,19 @@ NTSTATUS WINAPI NtOpenJobObject( PHANDLE handle, ACCESS_MASK access, const OBJEC
*/
NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
{
- FIXME( "stub: %p %x\n", handle, status );
- return STATUS_SUCCESS;
+ NTSTATUS ret;
+
+ TRACE( "(%p, %d)\n", handle, status );
+
+ SERVER_START_REQ( terminate_job )
+ {
+ req->handle = wine_server_obj_handle( handle );
+ req->status = status;
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return ret;
}
/******************************************************************************
@@ -624,8 +636,17 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info,
ULONG len, PULONG ret_len )
{
- FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
- return STATUS_NOT_IMPLEMENTED;
+ TRACE( "%p %u %p %u %p\n", handle, class, info, len, ret_len );
+
+ if (class >= MaxJobObjectInfoClass)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (class)
+ {
+ default:
+ FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
+ return STATUS_NOT_IMPLEMENTED;
+ }
}
/******************************************************************************
diff --git a/server/process.c b/server/process.c
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
static struct security_descriptor *process_get_sd( struct object *obj );
static void process_poll_event( struct fd *fd, int event );
static void process_destroy( struct object *obj );
+static void terminate_process( struct process *process, struct thread *skip, int exit_code );
static const struct object_ops process_ops =
{
@@ -148,6 +149,7 @@ struct job
struct list process_list; /* list of all processes */
int num_processes; /* count of running processes */
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 */
};
@@ -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->terminating = 0;
job->completion_port = NULL;
job->completion_key = 0;
}
@@ -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;
+
+ /* find the first process associcated with this job and still running */
+ LIST_FOR_EACH_ENTRY( process, &job->process_list, struct process, job_entry )
+ {
+ if (process->running_threads) break;
+ }
+ if (&process->job_entry == &job->process_list) break; /* no process found */
+ 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;
@@ -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) return;
+
+ terminate_job( job, req->status );
+ 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
+++ b/server/process.h
@@ -26,6 +26,7 @@
struct atom_table;
struct handle_table;
struct startup_info;
+struct job;
/* process startup state */
enum startup_state { STARTUP_IN_PROGRESS, STARTUP_DONE, STARTUP_ABORTED };
diff --git a/server/protocol.def b/server/protocol.def
index 9199c7f..5ecc8d5 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -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 */
+ int status; /* exitcode of the process */
+@END
+
+
/* Set limit flags on a job */
@REQ(set_job_limits)
obj_handle_t handle; /* handle to the job */
--
2.3.3

View File

@@ -1,32 +1,31 @@
From 55894316559d36c433e8aa8ae6e6957fa651d09a Mon Sep 17 00:00:00 2001
From 32940d62072444eb41a918b27aae6e4b48fe555f Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 12 Mar 2015 22:19:50 +0100
Subject: ntdll: Implement NtQueryInformationJobObject stub function.
---
dlls/ntdll/sync.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
dlls/ntdll/sync.c | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 87ff3e0..9a7a6d0 100644
index 04c6de30..fb95460 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -636,15 +636,37 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
@@ -635,8 +635,37 @@ NTSTATUS WINAPI NtTerminateJobObject( HANDLE handle, NTSTATUS status )
NTSTATUS WINAPI NtQueryInformationJobObject( HANDLE handle, JOBOBJECTINFOCLASS class, PVOID info,
ULONG len, PULONG ret_len )
{
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION *extended_limit;
+ JOBOBJECT_BASIC_LIMIT_INFORMATION *basic_limit;
+
TRACE( "%p %u %p %u %p\n", handle, class, info, len, ret_len );
if (class >= MaxJobObjectInfoClass)
return STATUS_INVALID_PARAMETER;
+ FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
- return STATUS_NOT_IMPLEMENTED;
+
switch (class)
{
+ if (class >= MaxJobObjectInfoClass)
+ return STATUS_INVALID_PARAMETER;
+
+ switch (class)
+ {
+ case JobObjectExtendedLimitInformation:
+ if (len < sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))
+ return STATUS_INVALID_PARAMETER;
@@ -45,11 +44,12 @@ index 87ff3e0..9a7a6d0 100644
+ if (ret_len) *ret_len = sizeof(*basic_limit);
+ return STATUS_SUCCESS;
+
default:
- FIXME( "stub: %p %u %p %u %p\n", handle, class, info, len, ret_len );
return STATUS_NOT_IMPLEMENTED;
}
+ default:
+ return STATUS_NOT_IMPLEMENTED;
+ }
}
/******************************************************************************
--
2.3.3
2.3.5

View File

@@ -1,115 +0,0 @@
From c86188e18efaf5ece7b4d85ccee4089208e392fa Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sat, 28 Feb 2015 06:09:16 +0100
Subject: kernel32/tests: Add tests for waiting on an job object.
---
dlls/kernel32/tests/process.c | 85 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 85 insertions(+)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 4f51cea..aaa1a6e 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2456,6 +2456,90 @@ static void test_KillOnJobClose(void)
CloseHandle(pi.hThread);
}
+static void test_WaitForJobObject(void)
+{
+ HANDLE job;
+ PROCESS_INFORMATION pi;
+ BOOL ret;
+ DWORD dwret;
+
+ /* test waiting for a job object when the process is killed */
+ job = pCreateJobObjectW(NULL, NULL);
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
+
+ dwret = WaitForSingleObject(job, 100);
+ ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
+
+ create_process("wait", &pi);
+
+ ret = pAssignProcessToJobObject(job, pi.hProcess);
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
+
+ dwret = WaitForSingleObject(job, 100);
+ ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
+
+ ret = pTerminateJobObject(job, 123);
+ ok(ret, "TerminateJobObject error %u\n", GetLastError());
+
+ dwret = WaitForSingleObject(job, 500);
+ todo_wine
+ ok(dwret == WAIT_OBJECT_0 || broken(dwret == WAIT_TIMEOUT),
+ "WaitForSingleObject returned %u\n", dwret);
+
+ if (dwret == WAIT_TIMEOUT) /* Win 2000/XP */
+ {
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ CloseHandle(job);
+ todo_wine
+ win_skip("TerminateJobObject doesn't signal job, skipping tests\n");
+ return;
+ }
+
+ /* the object is not reset immediately */
+ dwret = WaitForSingleObject(job, 100);
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ /* creating a new process doesn't reset the signalled state */
+ create_process("wait", &pi);
+
+ ret = pAssignProcessToJobObject(job, pi.hProcess);
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
+
+ dwret = WaitForSingleObject(job, 100);
+ ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
+
+ ret = pTerminateJobObject(job, 123);
+ ok(ret, "TerminateJobObject error %u\n", GetLastError());
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+
+ CloseHandle(job);
+
+ /* repeat the test, but this time the process terminates properly */
+ job = pCreateJobObjectW(NULL, NULL);
+ ok(job != NULL, "CreateJobObject error %u\n", GetLastError());
+
+ dwret = WaitForSingleObject(job, 100);
+ ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
+
+ create_process("exit", &pi);
+
+ ret = pAssignProcessToJobObject(job, pi.hProcess);
+ ok(ret, "AssignProcessToJobObject error %u\n", GetLastError());
+
+ dwret = WaitForSingleObject(job, 100);
+ ok(dwret == WAIT_TIMEOUT, "WaitForSingleObject returned %u\n", dwret);
+
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+ CloseHandle(job);
+}
+
static HANDLE test_AddSelfToJob(void)
{
HANDLE job;
@@ -2676,6 +2760,7 @@ START_TEST(process)
test_QueryInformationJobObject();
test_CompletionPort();
test_KillOnJobClose();
+ test_WaitForJobObject();
job = test_AddSelfToJob();
test_jobInheritance(job);
test_BreakawayOk(job);
--
2.3.3

View File

@@ -1,72 +0,0 @@
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.
---
dlls/kernel32/tests/process.c | 2 --
server/process.c | 7 ++++++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index aaa1a6e..c325d32 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -2482,7 +2482,6 @@ static void test_WaitForJobObject(void)
ok(ret, "TerminateJobObject error %u\n", GetLastError());
dwret = WaitForSingleObject(job, 500);
- todo_wine
ok(dwret == WAIT_OBJECT_0 || broken(dwret == WAIT_TIMEOUT),
"WaitForSingleObject returned %u\n", dwret);
@@ -2491,7 +2490,6 @@ static void test_WaitForJobObject(void)
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(job);
- todo_wine
win_skip("TerminateJobObject doesn't signal job, skipping tests\n");
return;
}
diff --git a/server/process.c b/server/process.c
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 */
unsigned int limit_flags; /* limit flags */
int terminating; /* job is terminating */
+ int signaled; /* job is signaled */
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;
job->limit_flags = 0;
job->terminating = 0;
+ job->signaled = 0;
job->completion_port = NULL;
job->completion_key = 0;
}
@@ -284,6 +286,8 @@ static void terminate_job( struct job *job, int exit_code )
}
job->terminating = 0;
+ job->signaled = 1;
+ wake_up( &job->obj, 0 );
}
static int job_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
@@ -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 )
{
- return 0;
+ struct job *job = (struct job *)obj;
+ return job->signaled;
}
struct ptid_entry
--
2.3.3

View File

@@ -1,7 +1,4 @@
Fixes: [33723] EA Origin needs support for job objects
Fixes: Properly track handle count of wineserver objects
Fixes: Python PIP needs better NtQueryInformationJobObject stub
Fixes: [38351] Ignore unsupported job object restrictions
Depends: kernel32-Console_Handles
Depends: server-OpenProcess
Depends: server-Misc_ACL