Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
General
GeneralPortable MacsHardwareNetworking
Applications
Mac ApplicationsEudoraFirefox / MozillaInternet ExplorerOutlook ExpressMS OfficeEntourageExcelPowerPointWordVirtual PCMedia PlayerOther MS Products
Programming
Mac ProgrammingCodeWarriorPerl
Country Specific
Australian Mac GroupUK Mac Group

Mac Forum / Programming / CodeWarrior / August 2005



Tip: Looking for answers? Try searching our database.

Writing Files asynchronously

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
grice@panamsat.com - 22 Aug 2005 18:06 GMT
I have a classic app that uses FSWrite to store text into a file.
Ocassionally the app hangs when FSWrite is referencing a file on a
remote volume (Sun Unix disk with an AppleTalk stack installed). The
app will hang indefinitely (or until the user restarts the machine).

The problem is probably someplace in the Unix driver code and the
company that produced that code is gone.

I would like to work around the hang condition so I thought I'd convert
the FSWrite call to a PBWriteAsync call so I could monitor the
operation and kill off the write operation if it exceeded some
reasonable threshold. I coded the call up.

I got the PBWriteAsync call to work to a point. If the call completes
successfully, all is good. But when the call fails to complete, the
code then proceeds to close the file without change and then the app
abruptly crashes.

I suspect that the PBWrite request is actually completing after the
file is closed and writing over something that should remain untouched
by errant applications.

So I went looking for a way to kill off the pending I/O request.

KillIO seemed like an obvious choice at first but I soon discovered it
was intended to be used at the device driver level rather then the file
I/O level.

So I'm hunting for a function equivalent to KillIO that I can use with
an async file write operation.

Is there such a thing or is there a better way to work around my
original problem?

Your thoughts please.

Gary
Inverter - 22 Aug 2005 19:30 GMT
Well, I don't know anything about Classic, but I would pretty muc
expect that what you are trying is in general impossible:

When an application does a synchronous wirite, it might go ahead an
modify the data it just wrote out immediately after completing th
write ... so try to imagine what happens, when the write is no
performed asynchronously, i.e. the OS is writing out the data whil
your application is changing it!

So my thought is:"Surprising that there are cases where this works."

Inverte

--
Inverte

--
ipod 4g 20gb
mac mini 1.42ghz/80gb/1gb
powerbook 15\"/1.25ghz/80gb/1g
macosx.com - The Answer to Mac Support - http://www.macosx.co
David Phillip Oster - 28 Aug 2005 18:40 GMT
> Well, I don't know anything about Classic, but I would pretty much
> expect that what you are trying is in general impossible:
[quoted text clipped - 4 lines]
> performed asynchronously, i.e. the OS is writing out the data while
> your application is changing it!

It is the application's responsibility not to modify the data while the
write is alive. The author of the app just has to write it right. The
same issues occur in today in OS X, where it is easy to create threads,
any of which may write without blocking the other threads.

It IS difficult to write a correct multi-threaded program, and hell to
debug. Even NASA gets this wrong: the first Shuttle launch was scrubbed
because the 5 mirrored computers on the shuttle did not synchronize when
booted. The cause was a race condition with a 1 in 64 chance of
occurring.

Don't write multi-threaded programs (and that includes using asynch i/o)
unless you've passed a college-level exam on doing it. If you try to
just do it without some academic grounding in the subject, you'll get an
undebuggable mess.

Signature

David Phillip Oster

Jhnny Fvrt (it means "wa wa dance") - 29 Aug 2005 04:54 GMT
> Don't write multi-threaded programs (and that includes using asynch i/o)
> unless you've passed a college-level exam on doing it.

uh oh.  pet peeve alert.

personally, i think that advice is misguided.  yes, multi-threaded programs
are hard to get right.  but then that applies to almost everything programmers
have to do.  i'd say it's certainly better than the alternative, i.e., having
a program that beachballs all the time, because it performs long-running tasks
in the gui thread that should have been spun off independently.  in fact, i
think i'd go completely the other way, and say it's almost impossible to write
anything but toy programs that are *not* multi-threaded.

here's the trick, as i see it: make your threads completely independent from
each other.  if you're going to spawn a secondary thread, have it pull jobs
out of a locked input queue, and don't let it share any objects with your main
thread.  or launch a thread to do just one task, and it suicides when
finished.  when the thread needs to report its results, you can use [NSObject
performSelectorOnMainThread] or something similar.

in the heat of the moment, it's easy to think it'll be okay to share an object
"just this once," and put a lock around it.  and now you're that much closer
to the embrace of death, where thread 1 has locked object A and is trying to
lock object B, and thread 2 has locked object B and is trying to lock object
A, and now both threads are dead until you kill the program.  that's the most
common beginner's mistake in multi-threading, i think.  it's a wicked-hard
kind of problem to debug, because it probably only happens when the program is
under extreme stress, and you won't be able to duplicate it reliably.  i used
to fall victim to that one a lot.  the usual answer is: if you always lock
objects in the same order, it won't happen.  eh, i don't think that's
feasible.  you have to make use of too much knowledge that you're officially
not supposed to know, it breaks encapsulation.  so now i structure my
multi-threaded code so that no thread is ever holding more than one lock at a
time.  i almost never introduce new locks, i use them only for input queues.
yes, it's inconvenient, but i never have to worry about the embrace-of-death
problem.

it's not surprising to me that many programmers have the attitude that you do,
that threading is so hard that it should be avoided altogether.  that seems to
mostly be the attitude of the people making the OSes, as well!  every OS i've
ever used made threading much more difficult than it should be, *except* for
beos.  that one was architected from the very first line of code to be
multi-threaded, and it shows.  your advice would be completely useless there,
because it's impossible to write a beos gui program that is *not*
multi-threaded.  every beos window runs in its own thread.  but they make it
much more difficult to screw up, as well.  each window has its own
self-locking queue of input events.  by comparison, macosx's thread support
feels bolted on.

i'd say learning threading is easier than another common and difficult task:
large program management.  when a project gets up to around 40 or 50 thousand
lines, you have to start thinking long and hard about program organization, or
else you're going to have such a big mess on your hands that you can't fix a
bug without introducing two more.  i bet a lot of amateur projects end up
dying that way.  so that's another issue that doesn't get as much attention as
it should, and with similar bad results: amateurs are prevented from writing
projects that get past a certain size.

so i guess i'd agree to the extent that you can't just say "hey, i think i'll
add some threads to my program," because you'll probably screw it up the first
time. so don't do that in a bread-and-butter app that you're selling to
people.  but then that's true of pretty much everything new you try, isn't it?
i bet your very first mac program didn't exactly rival photoshop, am i right?
Kurt Bigler - 26 Aug 2005 02:18 GMT
> I have a classic app that uses FSWrite to store text into a file.
> Ocassionally the app hangs when FSWrite is referencing a file on a
[quoted text clipped - 29 lines]
> Is there such a thing or is there a better way to work around my
> original problem?

I guess there is no way to set the time-out to a lower value?  In any case
if it is the driver and not the OS that implements the time-out then this
may not help with a buggy driver.

I'm surprised to realize that there is no apparent way to unqueue a
parameter block request.  This seems hard to believe.

However, FWIW, check out FInitQueue which "clears all the queued File
Manager calls except the current one".  Maybe you can make this work.

I'd try to set some kind of a breakpoint (maybe use MacsBug) in your
ioCompletion routine to see if it gets called prior to the crash.  If you
don't have one, add one.  If you do, maybe it is your completion routine
that is crashing anyway.

As another possibility you might try altering the parameter block in order
to cancel the request (in effect).  You  might try setting ioReqCount to
zero.  Maybe this will cause the queued request to become more innocuous if
it eventually fires.  I have a vague memory that there may be a supported
way to alter a param block in order to cause the request to be cancelled.
Like maybe setting the ioResult to a certain value?

Presumably you are careful not to re-use the parameter block or associated
buffer before an existing use has completed.

-Kurt Bigler
David Phillip Oster - 26 Aug 2005 06:14 GMT
> I have a classic app that uses FSWrite to store text into a file.
> Ocassionally the app hangs when FSWrite is referencing a file on a
[quoted text clipped - 23 lines]
> was intended to be used at the device driver level rather then the file
> I/O level.

In Classic, you should be able to use KillIO to kill a PBWriteAsync,
even if it is to a file.

Just don't re-use the same parameter block for the KillIO that you used
for the PBWriteAsync.

Just a guess. I have no direct knowledge.

Signature

David Phillip Oster

 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.