View mode: basic / threaded / horizontal-split · Log in · Help
January 21, 2010
[dmd-concurrency] Shutdown protocol
On Thu, Jan 21, 2010 at 1:41 AM, Andrei Alexandrescu <andrei at erdani.com>wrote:

> Sean Kelly wrote:
>
>> On Jan 20, 2010, at 3:54 PM, Andrei Alexandrescu wrote:
>>
>>  Sean Kelly wrote:
>>>
>>>> On Jan 20, 2010, at 11:26 AM, Andrei Alexandrescu wrote:
>>>>
>>>>> I don't think so. When the two instances of the copy threads finish
>>>>> reading and sending messages to their writers, they return. As a
>>>>> consequence, wait returns. As a consequence, main finishes.
>>>>>
>>>>> At this critical point, we have the following situation:
>>>>>
>>>>> (a) main has finished, therefore the shutdown mode is in effect
>>>>>
>>>>> (b) There are a number of messages in flight containing buffers waiting
>>>>> to be written in the two files.
>>>>>
>>>>> The important thing to do is to NOT throw shutdown as long as calls to
>>>>> receive() would not block.
>>>>>
>>>> That sounds like a horrible race problem.
>>>>
>>>
>>> Not at all. On the contrary, it's the stark opposite of a race:
>>>
>>> * Readers only finish after they have sent all messages they had to send.
>>>
>>> * Application doesn't shutdown until all sent messages have been acted
>>> upon.
>>>
>>
>> If the reader is slower than the writer it's entirely possible that the
>> writer will block on receive() during processing.  The receiver really only
>> knows that it's done when it receives a message to that effect from the
>> reader thread. If the threads were linked then this might be a "normal"
>> shutdown message, for example.  Funny now that we're talking about this how
>> many use cases I'm thinking of for bidirectional linking.
>>
>
> I don't think so. Say the reader is moving at 1 byte/millenium and the
> writer is moving at 1 petabyte/femtosecond. So the writer will spend
> virtually all of its time blocked in receive().
>
> At the point the reader is finishing, the following actions happen in
> causal order:
>
> 1. The reader sends the last data message to the writer
>
> 2. The reader's function returns to main
>
> 3. main returns
>
> Regardless of the relative speeds of the reader and the writer, causality
> above stays the same. There can be no race.
>
>
> Andrei
>

Assuming one reader.  What about a scenario where there are several each of
readers and writers, maybe the data flow of 'diff' as a simple example?

In this case we should assume that main knows the tids of all the readers
rather than running them directly as in the two thread file copy example.
More generally, for any set of queues, main would need to knows about the
side that has to finish for completeness to be guaranteed, which seems like
it will be the side that is filling the queue, right?

So lets say that threads will normally fall into the three camps, that I'll
call producers, filters and processors.  Producers are anything that
produces data into the message passing system but is not feeding from a
queue to get its orders.  Filters are anything that is queue or
message-event driven but also write their results to a queue / mailbox, and
consumers, anything queue-fed but not sending output into queues.  Queue fed
here means not just that they read from queues some of the time but that
they can always be expected to look at the queue for their next input and
aren't going to be done until the queue is 'dry' or contains a shutdown
command.

Given that blob of definitions, what does main need to do?  I would say that
we can treat the whole graph of components as directional.  The consumers
are downstream, the filters are upstream, and the producers are as far up
the creek as you can get.  I think main needs the tids of all the producers
and needs to either wait on all of them for shutdown messages or tell them
all to shut down when needed.

Hmmm...

Maybe we can allow the threads to tell us these relationships -- threads
could specify other threads they depend on or simply are watching.  When any
(or all, configurably?) of a thread's dependencies disappear the thread gets
an OOB message which it can handle if needed.  All threads default to
depending on main; however, main could store its Tid somewhere and maybe a
Thread could even use this to intentionally remove this dependency (e.g. it
doesn't wanna die when main goes away).  Similarly, a thread could find out
which other threads depend on it.

Main could check if it has any dependents, if desired... (these last bits is
kind of off the cuff, so maybe there are huge problems with them.)

Kevin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/dmd-concurrency/attachments/20100121/74e8f6d2/attachment-0001.htm>
January 21, 2010
[dmd-concurrency] Shutdown protocol
Kevin Bealer wrote:
> Assuming one reader.  What about a scenario where there are several each 
> of readers and writers, maybe the data flow of 'diff' as a simple example?

In that case my analysis doesn't stand. A different approach should be 
devised.

> In this case we should assume that main knows the tids of all the 
> readers rather than running them directly as in the two thread file copy 
> example.  More generally, for any set of queues, main would need to 
> knows about the side that has to finish for completeness to be 
> guaranteed, which seems like it will be the side that is filling the 
> queue, right?

For general queues, a end-of-stream signal must travel. Michel made a 
good point that I should better define solid protocols even in simple 
examples, so I'll change the code accordingly.

> So lets say that threads will normally fall into the three camps, that 
> I'll call producers, filters and processors.
[snip]
> Main could check if it has any dependents, if desired... (these last 
> bits is kind of off the cuff, so maybe there are huge problems with them.)

This makes sense, but at this point I'd avoid classifications that don't 
have a precedent. If Erlang made it without thread kinds, we should too.


Andrei
January 21, 2010
[dmd-concurrency] Shutdown protocol
Le 2010-01-21 ? 3:14, Andrei Alexandrescu a ?crit :

>> So lets say that threads will normally fall into the three camps, that I'll call producers, filters and processors.
> [snip]
>> Main could check if it has any dependents, if desired... (these last bits is kind of off the cuff, so maybe there are huge problems with them.)
> 
> This makes sense, but at this point I'd avoid classifications that don't have a precedent. If Erlang made it without thread kinds, we should too.

Erlang has the notion of links between threads (or should I say process?). If you link thread B to thread A, when thread A completes thread B receives a message to that effect. The default action is to do nothing if thread A exited normally and abort if thread A exited abnormally. But of course thread B can handle the message differently.

When you think about it, it's pretty much what I proposed we do at the beginning of this thread. The difference were that I was proposing threads to be linked automatically with spawn (erlang use spawn_linked for this) and that threads get a shutdown message automatically when the owner thread terminates, terminating the thread by default (erlang only do this for abnormal termination, although you can change that behaviour in the linked thread's message handler).

I'm no expert on erlang, but that's what I understood from what I read (and cited on this list) yesterday.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/
January 21, 2010
[dmd-concurrency] Shutdown protocol
On Jan 21, 2010, at 12:14 AM, Andrei Alexandrescu wrote:

> Kevin Bealer wrote:
> 
>> So lets say that threads will normally fall into the three camps, that I'll call producers, filters and processors.
> [snip]
>> Main could check if it has any dependents, if desired... (these last bits is kind of off the cuff, so maybe there are huge problems with them.)
> 
> This makes sense, but at this point I'd avoid classifications that don't have a precedent. If Erlang made it without thread kinds, we should too.

To be fair, Erlang also doesn't have this shutdown behavior.
January 21, 2010
[dmd-concurrency] Shutdown protocol
Sean Kelly wrote:
> On Jan 21, 2010, at 12:14 AM, Andrei Alexandrescu wrote:
> 
>> Kevin Bealer wrote:
>>
>>> So lets say that threads will normally fall into the three camps, that I'll call producers, filters and processors.
>> [snip]
>>> Main could check if it has any dependents, if desired... (these last bits is kind of off the cuff, so maybe there are huge problems with them.)
>> This makes sense, but at this point I'd avoid classifications that don't have a precedent. If Erlang made it without thread kinds, we should too.
> 
> To be fair, Erlang also doesn't have this shutdown behavior.

There are two precedents for the proposed shutdown behavior. One is the 
behavior of sockets in both Unix and Windows networking library. The 
libraries have one entry point for shutting down the entire library, 
after which all pending or new calls fail immediately. For example, 
quoting from

http://msdn.microsoft.com/en-us/library/aa384350%28VS.85%29.aspx

"The function terminates any pending operations on the handle and 
discards any outstanding data. If a thread is blocking a call to 
Wininet.dll, another thread in the application can call 
InternetCloseHandle on the Internet handle being used by the first 
thread to cancel the operation and unblock the first thread."

This is why you can close a browser instantly even though there may be a 
dozen pages still waiting to load.

The second is Java's experiment ThreadDeath:

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ThreadDeath.html

That experiment failed because they couldn't find a reliable method for 
transforming the exception from aysnchronous to synchronous.

My idea combines these two.


Andrei
January 21, 2010
[dmd-concurrency] Shutdown protocol
----- Original Message ----

> From: Andrei Alexandrescu <andrei at erdani.com>
> 
> "The function terminates any pending operations on the handle and discards any 
> outstanding data. If a thread is blocking a call to Wininet.dll, another thread 
> in the application can call InternetCloseHandle on the Internet handle being 
> used by the first thread to cancel the operation and unblock the first thread."
> 
> This is why you can close a browser instantly even though there may be a dozen 
> pages still waiting to load.

I disagree.  A browser "closing instantly" just means its UI is hidden.  Watch the process in Task Manager, it lingers for quite a few seconds.

-Steve
January 21, 2010
[dmd-concurrency] Shutdown protocol
Steve Schveighoffer wrote:
> ----- Original Message ----
> 
>> From: Andrei Alexandrescu <andrei at erdani.com>
>>
>> "The function terminates any pending operations on the handle and discards any 
>> outstanding data. If a thread is blocking a call to Wininet.dll, another thread 
>> in the application can call InternetCloseHandle on the Internet handle being 
>> used by the first thread to cancel the operation and unblock the first thread."
>>
>> This is why you can close a browser instantly even though there may be a dozen 
>> pages still waiting to load.
> 
> I disagree.  A browser "closing instantly" just means its UI is hidden.  Watch the process in Task Manager, it lingers for quite a few seconds.

The actual process shutdowns next to instantly on all my computers. I 
can say I'm positive it does not use the method you are suggesting in 
your other message (readWithShutdown).


Andrei
January 21, 2010
[dmd-concurrency] Shutdown protocol
----- Original Message ----

> From: Andrei Alexandrescu <andrei at erdani.com>
> Steve Schveighoffer wrote:
> > ----- Original Message ----
> > 
> >> From: Andrei Alexandrescu 
> >> 
> >> "The function terminates any pending operations on the handle and discards 
> any outstanding data. If a thread is blocking a call to Wininet.dll, another 
> thread in the application can call InternetCloseHandle on the Internet handle 
> being used by the first thread to cancel the operation and unblock the first 
> thread."
> >> 
> >> This is why you can close a browser instantly even though there may be a 
> dozen pages still waiting to load.
> > 
> > I disagree.  A browser "closing instantly" just means its UI is hidden.  Watch 
> the process in Task Manager, it lingers for quite a few seconds.
> 
> The actual process shutdowns next to instantly on all my computers. I can say 
> I'm positive it does not use the method you are suggesting in your other message 
> (readWithShutdown).
> 

I can't say what method it uses to shut down.  I don't see how you can either unless you read the code.

What I can say is I've seen Firefox linger and even hang when I shut it down.  Often times I accidentally shut down firefox, and go to reopen it in about 5 seconds, and it says it can't start because there's already a process running and that process is shutting down.  Clearly it does some sort of cleanup, whether part of that is to wait for socket reads to time out, I'm not sure.

My larger point, however, is that the socket-shutdown facility you want to have is available to D applications.  But making it a *required* part is too much.  Maybe applications that don't shut down using this method don't make it on to your laptop, but that's hardly a reason to require all D applications to do it.  You are not the only user of D applications, and web browsing is not the only use-case for threading and sockets.

-Steve
January 21, 2010
[dmd-concurrency] Shutdown protocol
Exactly.  I would love having some way to designate a master thread,  
but I don't want it imposed on me.

Sent from my iPhone

On Jan 21, 2010, at 9:27 AM, Steve Schveighoffer <schveiguy at yahoo.com>  
wrote:

> ----- Original Message ----
>
>> From: Andrei Alexandrescu <andrei at erdani.com>
>> Steve Schveighoffer wrote:
>>> ----- Original Message ----
>>>
>>>> From: Andrei Alexandrescu
>>>>
>>>> "The function terminates any pending operations on the handle and  
>>>> discards
>> any outstanding data. If a thread is blocking a call to  
>> Wininet.dll, another
>> thread in the application can call InternetCloseHandle on the  
>> Internet handle
>> being used by the first thread to cancel the operation and unblock  
>> the first
>> thread."
>>>>
>>>> This is why you can close a browser instantly even though there  
>>>> may be a
>> dozen pages still waiting to load.
>>>
>>> I disagree.  A browser "closing instantly" just means its UI is  
>>> hidden.  Watch
>> the process in Task Manager, it lingers for quite a few seconds.
>>
>> The actual process shutdowns next to instantly on all my computers.  
>> I can say
>> I'm positive it does not use the method you are suggesting in your  
>> other message
>> (readWithShutdown).
>>
>
> I can't say what method it uses to shut down.  I don't see how you  
> can either unless you read the code.
>
> What I can say is I've seen Firefox linger and even hang when I shut  
> it down.  Often times I accidentally shut down firefox, and go to  
> reopen it in about 5 seconds, and it says it can't start because  
> there's already a process running and that process is shutting  
> down.  Clearly it does some sort of cleanup, whether part of that is  
> to wait for socket reads to time out, I'm not sure.
>
> My larger point, however, is that the socket-shutdown facility you  
> want to have is available to D applications.  But making it a  
> *required* part is too much.  Maybe applications that don't shut  
> down using this method don't make it on to your laptop, but that's  
> hardly a reason to require all D applications to do it.  You are not  
> the only user of D applications, and web browsing is not the only  
> use-case for threading and sockets.
>
> -Steve
>
>
>
>
> _______________________________________________
> dmd-concurrency mailing list
> dmd-concurrency at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-concurrency
January 21, 2010
[dmd-concurrency] Shutdown protocol
----- Original Message ----
> From: Andrei Alexandrescu <andrei at erdani.com>
> 
> Sean Kelly wrote:
> > On Jan 21, 2010, at 12:14 AM, Andrei Alexandrescu wrote:
> > 
> >> Kevin Bealer wrote:
> >> 
> >>> So lets say that threads will normally fall into the three camps, that I'll 
> call producers, filters and processors.
> >> [snip]
> >>> Main could check if it has any dependents, if desired... (these last bits is 
> kind of off the cuff, so maybe there are huge problems with them.)
> >> This makes sense, but at this point I'd avoid classifications that don't have 
> a precedent. If Erlang made it without thread kinds, we should too.
> > 
> > To be fair, Erlang also doesn't have this shutdown behavior.
> 
> There are two precedents for the proposed shutdown behavior. One is the behavior 
> of sockets in both Unix and Windows networking library. The libraries have one 
> entry point for shutting down the entire library, after which all pending or new 
> calls fail immediately. For example, quoting from
> 
> http://msdn.microsoft.com/en-us/library/aa384350%28VS.85%29.aspx
> 
> "The function terminates any pending operations on the handle and discards any 
> outstanding data. If a thread is blocking a call to Wininet.dll, another thread 
> in the application can call InternetCloseHandle on the Internet handle being 
> used by the first thread to cancel the operation and unblock the first thread."
> 
> This is why you can close a browser instantly even though there may be a dozen 
> pages still waiting to load.

This facility is http and ftp specific, and only works if you use Windows' WinInet library:

"The Microsoft Windows Internet (WinINet) application programming
interface (API) enables applications to access standard Internet
protocols, such as FTP and HTTP. For ease of use, WinINet abstracts
these protocols into a high-level interface."

All sockets can be cleaned up with WSACleanup:

http://msdn.microsoft.com/en-us/library/ms741549%28VS.85%29.aspx

Which appears to do what you want -- except if you are calling it from DllMain:

"The WSACleanup function typically leads to protocol-specific helper DLLs being unloaded. As a result, the WSACleanup function should not be called from the
DllMain function in a application DLL. This can potentially cause
deadlocks. For more information, please see the DLL Main Function."

I don't think we should use this.

-Steve
1 2 3 4 5 6 7 8
Top | Discussion index | About this forum | D home