Github user JoshRosen commented on the pull request:

    https://github.com/apache/spark/pull/2838#issuecomment-59632902
  
    The `take()`-handling code is a little tricky and has been the source of 
multiple bugs in the past, so it may be worth considering several different 
approaches for fixing this; I would hate for this problem to re-occur again.
    
    For those who are unfamiliar with this code / issue, here a quick summary 
of this issue:
    
    - When I call `take()` in PySpark, this translates down to a 
`mapPartitions()` call where the map function returns the `take()` results 
before consuming all of the partition's iterator.
    - As a result, Python workers can complete their tasks before their input 
writers are closed.
    - Previously, this could lead to various IOExceptions because the Java 
thread that writes the Python worker's input would still be running when the 
Python worker process shut down on task completion.
    - Now that we re-use workers, the unread data written by the Java data 
writer thread will be left in the socket.  This causes problems for subsequent 
tasks run on that worker, since the worker attempts to interpret whatever 
random data was left in the socket as Python code, configuration settings, etc.
    - This bug, like the old IOException issue, only surfaces in cases where we 
have a large partition and a small `take()` size.  If the partition is small or 
the `take()` is big, this stdin writer thread's output may be completely read 
by the worker.  Basically, there's a race condition here which is data-size / 
take-size dependent.
    
    This PR proposes to fix this by having the worker check the input stream to 
determine whether there was unread data left in the stream.  If so, the worker 
exits and is not re-used.
    
    I have two questions:
    
    - Is there an approach that allows the worker to be (safely) re-used?
    - Is there a less-brittle way to check whether the worker has consumed all 
of its input?  I think we might be able to do this by calling `next()` on the 
input stream after we have run the user-provided code and checking for the 
"end-of-stream" code there, or checking for it inside of the serializers 
themselves.  As I explained in [my comment in the 
diff](https://github.com/apache/spark/pull/2838#discussion_r19056687), I think 
that this may be less brittle in the face of future changes to our 
serialization code.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to