mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Added patch for job object completion support.
This commit is contained in:
parent
cd62b5bedc
commit
8cc25d0fe4
@ -38,12 +38,13 @@ Wine. All those differences are also documented on the
|
||||
Included bug fixes and improvements
|
||||
===================================
|
||||
|
||||
**Bugfixes and features included in the next upcoming release [10]:**
|
||||
**Bugfixes and features included in the next upcoming release [11]:**
|
||||
|
||||
* Add stub for gdiplus.GdipCreateEffect ([Wine Bug #32163](https://bugs.winehq.org/show_bug.cgi?id=32163))
|
||||
* Add support for CopyFileEx progress callback ([Wine Bug #22692](https://bugs.winehq.org/show_bug.cgi?id=22692))
|
||||
* Allow to cancel a file operation via progress callback ([Wine Bug #22690](https://bugs.winehq.org/show_bug.cgi?id=22690))
|
||||
* Allow to override number of quality levels for D3DMULTISAMPLE_NONMASKABLE. ([Wine Bug #12652](https://bugs.winehq.org/show_bug.cgi?id=12652))
|
||||
* EA Origin needs support for job objects ([Wine Bug #33723](https://bugs.winehq.org/show_bug.cgi?id=33723))
|
||||
* Enforce that surfaces are flushed after ReleaseDC
|
||||
* Fallback to global key state for threads without a queue ([Wine Bug #27238](https://bugs.winehq.org/show_bug.cgi?id=27238))
|
||||
* Fix race-condition when threads are killed during shutdown
|
||||
|
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -19,6 +19,7 @@ wine-staging (1.7.38) UNRELEASED; urgency=low
|
||||
* Added patch to enforce that surfaces are flushed after ReleaseDC.
|
||||
* Added patch to implement IProgressDialog::SetAnimation.
|
||||
* Added patch in order to allow to override number of quality levels for D3DMULTISAMPLE_NONMASKABLE.
|
||||
* Added patch for job object completion support.
|
||||
* Removed patch to properly call DriverUnload when unloading device drivers (accepted upstream).
|
||||
* Removed patch to allow Accept-Encoding for HTTP/1.0 in wininet (accepted upstream).
|
||||
* Removed patch to declare pDirectInputCreateEx in a MSVC compatible way (accepted upstream).
|
||||
|
@ -3338,6 +3338,9 @@ fi
|
||||
|
||||
# Patchset server-JobObjects
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#33723] EA Origin needs support for job objects
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/kernel32/tests/process.c, dlls/ntdll/sync.c, include/winnt.h, server/process.c, server/process.h,
|
||||
# | server/protocol.def
|
||||
@ -3353,6 +3356,7 @@ if test "$enable_server_JobObjects" -eq 1; then
|
||||
patch_apply server-JobObjects/0008-kernel32-tests-Add-tests-for-JOB_OBJECT_LIMIT_BREAKA.patch
|
||||
patch_apply server-JobObjects/0009-kernel32-tests-Add-tests-for-job-inheritance.patch
|
||||
patch_apply server-JobObjects/0010-server-Basic-implementation-of-job-objects.patch
|
||||
patch_apply server-JobObjects/0011-server-Implement-completion-messages-for-job-objects.patch
|
||||
(
|
||||
echo '+ { "Sebastian Lackner", "kernel32/tests: Allow multiple subprocess commands in process tests.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for IsProcessInJob.", 1 },';
|
||||
@ -3364,6 +3368,7 @@ if test "$enable_server_JobObjects" -eq 1; then
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for JOB_OBJECT_LIMIT_BREAKAWAY_OK.", 1 },';
|
||||
echo '+ { "Andrew Cook", "kernel32/tests: Add tests for job inheritance.", 1 },';
|
||||
echo '+ { "Andrew Cook", "server: Basic implementation of job objects.", 1 },';
|
||||
echo '+ { "Andrew Cook", "server: Implement completion messages for job objects.", 1 },';
|
||||
) >> "$patchlist"
|
||||
fi
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 42af9f44c92dbe151b3ec5b4f57e941133349648 Mon Sep 17 00:00:00 2001
|
||||
From bc3809dc809edebc43305826f2a687de1089ca26 Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Cook <ariscop@gmail.com>
|
||||
Date: Thu, 26 Feb 2015 12:25:23 +1100
|
||||
Subject: server: Basic implementation of job objects.
|
||||
@ -15,10 +15,10 @@ Changes by Sebastian Lackner <sebastian@fds-team.de>:
|
||||
dlls/kernel32/tests/process.c | 8 +-
|
||||
dlls/ntdll/sync.c | 139 ++++++++++++++++++++---
|
||||
include/winnt.h | 4 +
|
||||
server/process.c | 256 ++++++++++++++++++++++++++++++++++++++++++
|
||||
server/process.c | 254 ++++++++++++++++++++++++++++++++++++++++++
|
||||
server/process.h | 3 +
|
||||
server/protocol.def | 27 +++++
|
||||
6 files changed, 417 insertions(+), 20 deletions(-)
|
||||
6 files changed, 415 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 9d7d8b8..3f78d74 100644
|
||||
@ -288,7 +288,7 @@ index 4b06b2c..c2aa50e 100644
|
||||
{
|
||||
RelationProcessorCore = 0,
|
||||
diff --git a/server/process.c b/server/process.c
|
||||
index 0712a5b..850a9c8 100644
|
||||
index 0712a5b..5770f0e 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
|
||||
@ -509,7 +509,7 @@ index 0712a5b..850a9c8 100644
|
||||
/* connect to the window station */
|
||||
connect_process_winstation( process, current );
|
||||
|
||||
@@ -1361,3 +1530,90 @@ DECL_HANDLER(make_process_system)
|
||||
@@ -1361,3 +1530,88 @@ DECL_HANDLER(make_process_system)
|
||||
shutdown_timeout = add_timeout_user( master_socket_timeout, server_shutdown_timeout, NULL );
|
||||
}
|
||||
}
|
||||
@ -545,59 +545,57 @@ index 0712a5b..850a9c8 100644
|
||||
+DECL_HANDLER(job_assign)
|
||||
+{
|
||||
+ struct process *process;
|
||||
+ struct job *job;
|
||||
+ struct job *job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS );
|
||||
+
|
||||
+ if (!(job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS )))
|
||||
+ return;
|
||||
+
|
||||
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_SET_QUOTA | PROCESS_TERMINATE )))
|
||||
+ if (job)
|
||||
+ {
|
||||
+ add_job_process( job, process );
|
||||
+ release_object(process);
|
||||
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_SET_QUOTA | PROCESS_TERMINATE )))
|
||||
+ {
|
||||
+ add_job_process( job, process );
|
||||
+ release_object(process);
|
||||
+ }
|
||||
+ release_object(job);
|
||||
+ }
|
||||
+
|
||||
+ release_object(job);
|
||||
+}
|
||||
+
|
||||
+/* check if a process is associated with a job */
|
||||
+DECL_HANDLER(process_in_job)
|
||||
+{
|
||||
+ struct process *process;
|
||||
+ struct job *job;
|
||||
+ struct job *job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS );
|
||||
+
|
||||
+ if (!(job = get_job_obj( current->process, req->job_handle, JOB_OBJECT_ASSIGN_PROCESS )))
|
||||
+ return;
|
||||
+
|
||||
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_QUERY_INFORMATION )))
|
||||
+ if (job)
|
||||
+ {
|
||||
+ set_error((process->job == job) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB);
|
||||
+ release_object(process);
|
||||
+ if ((process = get_process_from_handle( req->process_handle, PROCESS_QUERY_INFORMATION )))
|
||||
+ {
|
||||
+ set_error( (process->job == job) ? STATUS_PROCESS_IN_JOB : STATUS_PROCESS_NOT_IN_JOB );
|
||||
+ release_object( process );
|
||||
+ }
|
||||
+ release_object(job);
|
||||
+ }
|
||||
+
|
||||
+ release_object(job);
|
||||
+}
|
||||
+
|
||||
+/* terminate all processes associated with the job */
|
||||
+DECL_HANDLER(terminate_job)
|
||||
+{
|
||||
+ struct job *job;
|
||||
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_TERMINATE );
|
||||
+
|
||||
+ if ((job = get_job_obj( current->process, req->handle, JOB_OBJECT_TERMINATE )))
|
||||
+ if (job)
|
||||
+ {
|
||||
+ terminate_job(job, req->status);
|
||||
+ release_object(job);
|
||||
+ terminate_job( job, req->status );
|
||||
+ release_object( job );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* update limits of the job object */
|
||||
+DECL_HANDLER(job_set_limits)
|
||||
+{
|
||||
+ struct job *job;
|
||||
+ struct job *job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES );
|
||||
+
|
||||
+ if ((job = get_job_obj( current->process, req->handle, JOB_OBJECT_SET_ATTRIBUTES )))
|
||||
+ if (job)
|
||||
+ {
|
||||
+ job->limit_flags = req->limit_flags;
|
||||
+ release_object(job);
|
||||
+ release_object( job );
|
||||
+ }
|
||||
+}
|
||||
diff --git a/server/process.h b/server/process.h
|
||||
|
@ -0,0 +1,196 @@
|
||||
From 71738db8658662f68f156ce95d146de2eb68b9cf 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 | 44 +++++++++++++++++++++++++++++++++++++++++++
|
||||
server/protocol.def | 6 ++++++
|
||||
4 files changed, 65 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
|
||||
index 3f78d74..ec79418 100644
|
||||
--- a/dlls/kernel32/tests/process.c
|
||||
+++ b/dlls/kernel32/tests/process.c
|
||||
@@ -2393,7 +2393,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);
|
||||
@@ -2401,16 +2400,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, (LPOVERLAPPED)pi.dwProcessId, 0);
|
||||
|
||||
TerminateProcess(pi.hProcess, 0);
|
||||
dwret = WaitForSingleObject(pi.hProcess, 500);
|
||||
ok(dwret == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", dwret);
|
||||
|
||||
- todo_wine
|
||||
test_completion(port, JOB_OBJECT_MSG_EXIT_PROCESS, (DWORD_PTR)job, (LPOVERLAPPED)pi.dwProcessId, 0);
|
||||
- todo_wine
|
||||
test_completion(port, JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO, (DWORD_PTR)job, NULL, 100);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
|
||||
index 56714ef..ef4a4cb 100644
|
||||
--- a/dlls/ntdll/sync.c
|
||||
+++ b/dlls/ntdll/sync.c
|
||||
@@ -696,6 +696,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( job_set_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 5770f0e..73fe08a 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 int add_job_process( struct job *job, struct process *process )
|
||||
{
|
||||
assert( job->obj.ops == &job_ops );
|
||||
@@ -228,6 +240,7 @@ static int add_job_process( struct job *job, struct process *process )
|
||||
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) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -242,10 +255,20 @@ static void release_job_process( struct process *process )
|
||||
assert( job->obj.ops == &job_ops );
|
||||
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;
|
||||
@@ -259,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 )
|
||||
@@ -268,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 )
|
||||
@@ -1615,3 +1643,19 @@ DECL_HANDLER(job_set_limits)
|
||||
release_object( job );
|
||||
}
|
||||
}
|
||||
+
|
||||
+DECL_HANDLER(job_set_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 cc39ef1..126c2a7 100644
|
||||
--- a/server/protocol.def
|
||||
+++ b/server/protocol.def
|
||||
@@ -709,6 +709,12 @@ struct rawinput_device
|
||||
unsigned int limit_flags;
|
||||
@END
|
||||
|
||||
+@REQ(job_set_completion)
|
||||
+ obj_handle_t handle;
|
||||
+ obj_handle_t port;
|
||||
+ client_ptr_t key;
|
||||
+@END
|
||||
+
|
||||
/* Retrieve information about a newly started process */
|
||||
@REQ(get_new_process_info)
|
||||
obj_handle_t info; /* info handle returned from new_process_request */
|
||||
--
|
||||
2.3.0
|
||||
|
@ -1,3 +1,4 @@
|
||||
Fixes: [33723] EA Origin needs support for job objects
|
||||
Depends: kernel32-Console_Handles
|
||||
Depends: server-OpenProcess
|
||||
Depends: server-Misc_ACL
|
||||
|
Loading…
x
Reference in New Issue
Block a user