Kill a running thread
What happens if we forcefully kill a running thread
I have a thread namely RecordThread()
which calls some complex and time consuming functions. In these functions I am using try-catch blocks, allocating and deallocation memory and using critical section variables etc.
like
void RecordThread()
{
AddRecord();
FindRecord();
DeleteRecord();
// ...
ExitThread(0);
}
After creating this thread, I am immediately killing it before the thread completes its execution. In this case what happens if the thread is forcefully killed? Do the internal functions (AddRecord
, DeleteRecord
) complete their execution after we killed the thread?
c++ windows multithreading
add a comment |
What happens if we forcefully kill a running thread
I have a thread namely RecordThread()
which calls some complex and time consuming functions. In these functions I am using try-catch blocks, allocating and deallocation memory and using critical section variables etc.
like
void RecordThread()
{
AddRecord();
FindRecord();
DeleteRecord();
// ...
ExitThread(0);
}
After creating this thread, I am immediately killing it before the thread completes its execution. In this case what happens if the thread is forcefully killed? Do the internal functions (AddRecord
, DeleteRecord
) complete their execution after we killed the thread?
c++ windows multithreading
add a comment |
What happens if we forcefully kill a running thread
I have a thread namely RecordThread()
which calls some complex and time consuming functions. In these functions I am using try-catch blocks, allocating and deallocation memory and using critical section variables etc.
like
void RecordThread()
{
AddRecord();
FindRecord();
DeleteRecord();
// ...
ExitThread(0);
}
After creating this thread, I am immediately killing it before the thread completes its execution. In this case what happens if the thread is forcefully killed? Do the internal functions (AddRecord
, DeleteRecord
) complete their execution after we killed the thread?
c++ windows multithreading
What happens if we forcefully kill a running thread
I have a thread namely RecordThread()
which calls some complex and time consuming functions. In these functions I am using try-catch blocks, allocating and deallocation memory and using critical section variables etc.
like
void RecordThread()
{
AddRecord();
FindRecord();
DeleteRecord();
// ...
ExitThread(0);
}
After creating this thread, I am immediately killing it before the thread completes its execution. In this case what happens if the thread is forcefully killed? Do the internal functions (AddRecord
, DeleteRecord
) complete their execution after we killed the thread?
c++ windows multithreading
c++ windows multithreading
edited Sep 22 '15 at 13:44
Wolf
5,29532776
5,29532776
asked May 24 '12 at 12:23
Aneesh Narayanan
1,27282341
1,27282341
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
After creating this thread, I am immediately killing it before the thread completes its execution.
I assume you mean you are using TerminateThread()
in the following fashion:
HANDLE thread = CreateThread(...);
// ...
// short pause or other action?
// ...
TerminateThread(thread, 0); // Dangerous source of errors!
CloseHandle(thread);
If that is the case, then no, the thread executing RecordThread()
will be stopped exactly where it is at the time that the other thread calls TerminateThread()
. As per the notes in the TerminateThread()
documentation, this exact point is somewhat random and depends on complex timing issues which are out of your control. This implies that you can't handle proper cleanup inside a thread and thus, you should rarely, if ever, kill a thread.
The proper way to request the thread to finish is by using WaitForSingleObject()
like so:
HANDLE thread = CreateThread(...);
// ...
// some other action?
// ...
// you can pass a short timeout instead and kill the thread if it hasn't
// completed when the timeout expires.
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
1
To make it more explicit:TerminateThread
can kill your thread in the middle of ani++
statement. It doesn't try to look for "nice" points such as function calls.
– MSalters
May 24 '12 at 12:50
1
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
add a comment |
killing thread is the last resort - as Andre stated it leaves data in unknown state, you should never do that if thread works on shared object. Better choices are to notify thread to finish work by:
-using global volatile (important) variable which is changed only by main thread and tested by workers
-using signal type synchronization objects (mainly Events) also set by main thread and tested by workers
add a comment |
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx
ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
However the function calls will of course be completed because they're called before the ExitThread().
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
add a comment |
example of Thread that works well:
definition in *.h ------------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData);
CThread th_espectro(Th_EspectroIF);
use in *.cc -----------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData)
{
//Your code...
th_espectro.Stop(true);//stop this Thread
}
call the Thread with: th_espectro.Start();
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f10737417%2fkill-a-running-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
After creating this thread, I am immediately killing it before the thread completes its execution.
I assume you mean you are using TerminateThread()
in the following fashion:
HANDLE thread = CreateThread(...);
// ...
// short pause or other action?
// ...
TerminateThread(thread, 0); // Dangerous source of errors!
CloseHandle(thread);
If that is the case, then no, the thread executing RecordThread()
will be stopped exactly where it is at the time that the other thread calls TerminateThread()
. As per the notes in the TerminateThread()
documentation, this exact point is somewhat random and depends on complex timing issues which are out of your control. This implies that you can't handle proper cleanup inside a thread and thus, you should rarely, if ever, kill a thread.
The proper way to request the thread to finish is by using WaitForSingleObject()
like so:
HANDLE thread = CreateThread(...);
// ...
// some other action?
// ...
// you can pass a short timeout instead and kill the thread if it hasn't
// completed when the timeout expires.
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
1
To make it more explicit:TerminateThread
can kill your thread in the middle of ani++
statement. It doesn't try to look for "nice" points such as function calls.
– MSalters
May 24 '12 at 12:50
1
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
add a comment |
After creating this thread, I am immediately killing it before the thread completes its execution.
I assume you mean you are using TerminateThread()
in the following fashion:
HANDLE thread = CreateThread(...);
// ...
// short pause or other action?
// ...
TerminateThread(thread, 0); // Dangerous source of errors!
CloseHandle(thread);
If that is the case, then no, the thread executing RecordThread()
will be stopped exactly where it is at the time that the other thread calls TerminateThread()
. As per the notes in the TerminateThread()
documentation, this exact point is somewhat random and depends on complex timing issues which are out of your control. This implies that you can't handle proper cleanup inside a thread and thus, you should rarely, if ever, kill a thread.
The proper way to request the thread to finish is by using WaitForSingleObject()
like so:
HANDLE thread = CreateThread(...);
// ...
// some other action?
// ...
// you can pass a short timeout instead and kill the thread if it hasn't
// completed when the timeout expires.
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
1
To make it more explicit:TerminateThread
can kill your thread in the middle of ani++
statement. It doesn't try to look for "nice" points such as function calls.
– MSalters
May 24 '12 at 12:50
1
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
add a comment |
After creating this thread, I am immediately killing it before the thread completes its execution.
I assume you mean you are using TerminateThread()
in the following fashion:
HANDLE thread = CreateThread(...);
// ...
// short pause or other action?
// ...
TerminateThread(thread, 0); // Dangerous source of errors!
CloseHandle(thread);
If that is the case, then no, the thread executing RecordThread()
will be stopped exactly where it is at the time that the other thread calls TerminateThread()
. As per the notes in the TerminateThread()
documentation, this exact point is somewhat random and depends on complex timing issues which are out of your control. This implies that you can't handle proper cleanup inside a thread and thus, you should rarely, if ever, kill a thread.
The proper way to request the thread to finish is by using WaitForSingleObject()
like so:
HANDLE thread = CreateThread(...);
// ...
// some other action?
// ...
// you can pass a short timeout instead and kill the thread if it hasn't
// completed when the timeout expires.
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
After creating this thread, I am immediately killing it before the thread completes its execution.
I assume you mean you are using TerminateThread()
in the following fashion:
HANDLE thread = CreateThread(...);
// ...
// short pause or other action?
// ...
TerminateThread(thread, 0); // Dangerous source of errors!
CloseHandle(thread);
If that is the case, then no, the thread executing RecordThread()
will be stopped exactly where it is at the time that the other thread calls TerminateThread()
. As per the notes in the TerminateThread()
documentation, this exact point is somewhat random and depends on complex timing issues which are out of your control. This implies that you can't handle proper cleanup inside a thread and thus, you should rarely, if ever, kill a thread.
The proper way to request the thread to finish is by using WaitForSingleObject()
like so:
HANDLE thread = CreateThread(...);
// ...
// some other action?
// ...
// you can pass a short timeout instead and kill the thread if it hasn't
// completed when the timeout expires.
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
edited May 23 '17 at 12:25
Community♦
11
11
answered May 24 '12 at 12:42
André Caron
33.9k848108
33.9k848108
1
To make it more explicit:TerminateThread
can kill your thread in the middle of ani++
statement. It doesn't try to look for "nice" points such as function calls.
– MSalters
May 24 '12 at 12:50
1
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
add a comment |
1
To make it more explicit:TerminateThread
can kill your thread in the middle of ani++
statement. It doesn't try to look for "nice" points such as function calls.
– MSalters
May 24 '12 at 12:50
1
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
1
1
To make it more explicit:
TerminateThread
can kill your thread in the middle of an i++
statement. It doesn't try to look for "nice" points such as function calls.– MSalters
May 24 '12 at 12:50
To make it more explicit:
TerminateThread
can kill your thread in the middle of an i++
statement. It doesn't try to look for "nice" points such as function calls.– MSalters
May 24 '12 at 12:50
1
1
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
Note that POSIX is much different from Win32 API in this respect (by default, unless the thread modified its cancellation settings), it will indeed only kill your thread at a cancellation point. So apart from being dangerous, it's not even equally dangerous everywhere, and thus not "portable" :-)
– Damon
Jul 18 '12 at 9:19
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
If it's not obvious from the other comments, some more reasons why you should never use TerminateThread: Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
– Robert P
Aug 17 '15 at 17:17
add a comment |
killing thread is the last resort - as Andre stated it leaves data in unknown state, you should never do that if thread works on shared object. Better choices are to notify thread to finish work by:
-using global volatile (important) variable which is changed only by main thread and tested by workers
-using signal type synchronization objects (mainly Events) also set by main thread and tested by workers
add a comment |
killing thread is the last resort - as Andre stated it leaves data in unknown state, you should never do that if thread works on shared object. Better choices are to notify thread to finish work by:
-using global volatile (important) variable which is changed only by main thread and tested by workers
-using signal type synchronization objects (mainly Events) also set by main thread and tested by workers
add a comment |
killing thread is the last resort - as Andre stated it leaves data in unknown state, you should never do that if thread works on shared object. Better choices are to notify thread to finish work by:
-using global volatile (important) variable which is changed only by main thread and tested by workers
-using signal type synchronization objects (mainly Events) also set by main thread and tested by workers
killing thread is the last resort - as Andre stated it leaves data in unknown state, you should never do that if thread works on shared object. Better choices are to notify thread to finish work by:
-using global volatile (important) variable which is changed only by main thread and tested by workers
-using signal type synchronization objects (mainly Events) also set by main thread and tested by workers
edited Jul 18 '12 at 9:26
answered Jul 18 '12 at 8:54
Piotr Tkaczyk
1275
1275
add a comment |
add a comment |
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx
ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
However the function calls will of course be completed because they're called before the ExitThread().
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
add a comment |
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx
ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
However the function calls will of course be completed because they're called before the ExitThread().
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
add a comment |
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx
ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
However the function calls will of course be completed because they're called before the ExitThread().
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx
ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.
However the function calls will of course be completed because they're called before the ExitThread().
answered May 24 '12 at 12:27
Vladimir Sinenko
3,46812135
3,46812135
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
add a comment |
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
What if they don't have enough time to complete?
– sharptooth
May 24 '12 at 12:29
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
@sharptooth like in single-threaded code, sequential consistency guarantees that all the lines before ExitThread() will complete.
– Erik van Velzen
Sep 6 '13 at 14:48
add a comment |
example of Thread that works well:
definition in *.h ------------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData);
CThread th_espectro(Th_EspectroIF);
use in *.cc -----------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData)
{
//Your code...
th_espectro.Stop(true);//stop this Thread
}
call the Thread with: th_espectro.Start();
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
add a comment |
example of Thread that works well:
definition in *.h ------------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData);
CThread th_espectro(Th_EspectroIF);
use in *.cc -----------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData)
{
//Your code...
th_espectro.Stop(true);//stop this Thread
}
call the Thread with: th_espectro.Start();
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
add a comment |
example of Thread that works well:
definition in *.h ------------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData);
CThread th_espectro(Th_EspectroIF);
use in *.cc -----------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData)
{
//Your code...
th_espectro.Stop(true);//stop this Thread
}
call the Thread with: th_espectro.Start();
example of Thread that works well:
definition in *.h ------------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData);
CThread th_espectro(Th_EspectroIF);
use in *.cc -----------------------------------
DWORD WINAPI Th_EspectroIF(LPVOID lpData)
{
//Your code...
th_espectro.Stop(true);//stop this Thread
}
call the Thread with: th_espectro.Start();
edited Nov 12 at 19:11
RalfFriedl
5771211
5771211
answered Nov 12 at 17:32
octavio oli
1
1
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
add a comment |
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
Welcome to Stack Overflow. Code-only answers are discouraged. How is this answer different from or better than previous answers?
– CGritton
Nov 12 at 17:53
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f10737417%2fkill-a-running-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown