CO527 Anonymous Questions and Answers |
This page lists the various questions and answers. To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.
We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.
I have two questions I would like to ask:
[snip if statement]
I have this `if' statement and I'm wondering:
should it be `(pid == from_pid)' or `pid == to_pid)' ?
it all compiles alright, but when I run it the output is:
process started, PID 3 UMailRecv -- mail-box receiver process UMailRecv: started message sender, pid 4 UMailSend -- mail-box sender process UMailSend: sending sleepy messages to PID 3... UMailRecv: got message [Hello, mailbox world 0 :)] UMailRecv: got message [Hello, mailbox world 1 :)] UMailRecv: got message [Hello, mailbox world 0 :)] UMailSend: done. exiting. UMailRecv: got message [Hello, mailbox world 3 :)] child exited with code 0 MOSS#
instead of from what I understand should be 0, 1, 2, 3. I'm pretty sure the problem is in that `if' statement somewhere but I can't really spot it, could you help me out?
In response to your first point, the test relating to the `pid' (user-supplied) parameter should be `(pid == from_pid)'. For your second question, yes, there is something wrong with that output. I'm not convinced it's the `if' test alone that's wrong -- once received, the duplicated message (0) should no longer be in the message-queue! One thing clearly missing from your `if' test is that of the receiver pid (i.e. ``(current.pid == to_pid)'').
On a more general point, you have an `if' statement of the form:
if ((A && B) || (C && B) || (A && D) || (C && D)) { ... }
this can be simplified to:
if ((A || C) && (B || D)) { ... }
My question is about `MPipe2', when the writer closes the pipe, I need to reschedule the reader, using the `MKernal.add_to_run_queue()' method. This method takes an `MProcess'. What I can't figure out is how to find out which `MProcess' is associated with the reader. Any help would be appreciated :).
When the writer closes the pipe, you can only reschedule the reader if it was blocked while trying to `read()' from the pipe. In this case, you will have stored a reference to it somewhere (possibly on an `MWaitQueue'). If the reader is not blocked on a `read()', then you shouldn't attempt to do anything to it -- it might be blocked somewhere else (or waiting on the run-queue).
When running the `UMailRecv' test I get all the messages but receive a `null' in middle of it:
MOSS# run UMailRecv process started, PID 3 UMailRecv -- mail-box receiver process UMailRecv: started message sender, pid 4 UMailSend -- mail-box sender process UMailSend: sending sleepy messages to PID 3... UMailRecv: MPosixIf.recvmsg() returned null! -- retry.. UMailRecv: got message [Hello, mailbox world 0 :)] UMailRecv: got message [Hello, mailbox world 1 :)] UMailSend: done. exiting. UMailRecv: MPosixIf.recvmsg() returned null! -- retry.. UMailRecv: got message [Hello, mailbox world 2 :)] UMailRecv: got message [Hello, mailbox world 3 :)] child exited with code 0
That's fine. When the `UMailSend' process terminates, `UMailRecv' is sent a SIGCHLD signal. In your case, the `UMailRecv' process was presumably blocked in `recvmsg()'. Thus, the signal woke it up and it returned `null' (as it should do).
In response to Question 54 (2003), why would:
private static ArrayList the_messages = new ArrayList();
not be so desirable ?
The main reason is that, in an operating system at least, we want initialisation to be explicit. Normally this would be done using a constructor, but since we're not creating objects, an explicit ``public static init_...()'' method is the `correct' alternative. It's entirely possible such initialisation might require more than simply setting up the various `local' (private static) variables.
Keywords: moss , initialisation
Am doing the mailbox option and am completely confused as to how I should get the `recvmsg()' to block while there are no messages. I have read the previous answers on the Q&A page and am still none the wiser... please help.
Some more questions relating to blocking in `recvmsg()' have been added; these should help explain this a bit more. In particular, see the answers to questions Question 75 (2003) and Question 66 (2003).
How can we have `MPipe2' implement `MFileOps', when we need to change the header for the `open' method (to use two file handles) ? Obviously, if it isn't implementing `MFileOps' it can't be used as an instance of `MFileOps' (as in `MPosixIf'). Is there a way of getting around this, because I can't figure it out!
You need to add an extra method to `MPipe2' to do this, rather than modifying the header of the existing `open()' method. The pipe is quite unique, however, since it is created and `open()'d in the same place (in `MPosixIf'). The following code fragment is from the `pipe()' method in `MPosixIf':
MPipe tp = new MPipe (); MFile fh = new MFile (); fh.refcount = 2; fh.fileif = tp; /* open the pipe (artificial!) */ tp.open (fh, 0); current.files[i] = fh; current.files[j] = fh; fds[0] = i; fds[1] = j;
This can be modified to incorporate the second `MFile' relatively easily. To solve the `open()' problem, you could add an `extra' `open()' method that takes two `MFile' parameters. Since the code in `MPosixIf' makes the `open()' call on an `MPipe' (rather than an `MFileOps'), using your new `open()' method (or whatever you decide to call it, `open2()' perhaps) is fine -- i.e. it doesn't matter that `MFileOps' doesn't support it; it's specific to the `pipe'.
For the `recvmsg()' method in `MPosixIf', it requires me to return an `Object'. But if there is no message for the process to receive, it has to block it by adding it to the `MWaitQueue', but what message is then returned ?
When `recvmsg()' has blocked, and subsequently been woken up, it should re-scan the message-queue. If a message is available, then that message should be returned. If not, then the process should go back to sleep (assuming that it wasn't woken up by a signal, as opposed to being woken up by `sendmsg()'). In the case that a blocked process was woken up by a signal, `recvmsg()' should return `null'.
When the process blocks, and then subsequently deschedules (by calling `MKernel.schedule()'), it can't return until it has been rescheduled (at which point the call to `MKernel.schedule()' returns).
For additional information, see the answers to Question 75 (2003), Question 66 (2003) and Question 18 (2003).
I have now got a good grip of what is going on in the MOSS assessment but I am a little confused over the blocking. I am doing the mail-box implementation and I don't know when processes should be blocking and which processes should block.
The way I'm currently thinking of things is as follows:
When a process calls `recvmsg()' - if it finds a message for itself (with the required `pid' and `type' if necessary), `recvmsg()' should return the `Object' storing the message.
If there is no matching message found, the process calling `recvmsg()' should add itself to the blocked processes queue and go to sleep.
Basically... am I heading down the right path with this code for my `recvmsg()' ?
[snip code]
Thanks in advance
Your thinking is correct. Looking at it, the code is largely correct too. There are two slight errors, however:
once a message has been found, your code continues scanning the remaining messages. It shouldn't do this -- it could go wrong.
when the blocked process has woken-up (returns from `MKernel.schedule()'), it checks to see if it's been signalled, removing itself from the `MWaitQueue' if so. Regardless of whether it was woken up by a signal or by `sendmsg()', `recvmsg()' will return `null'. This is correct if it was woken up by a signal (`current.signalled' is `true'), but not if it was woken up explicitly by `sendmsg()'. In the latter case, it should check the message-queue again and return a message if available -- otherwise it should go back to sleep.
Keywords: moss , mailbox , sleeping
Referrers: Question 104 (2003)
When I run the `UMailRecv' process, I get the following messages:
process started, PID 3 UMailRecv -- mail-box receiver process UMailRecv: started message sender, pid 4 UMailSend -- mail-box sender process UMailSend: sending sleepy messages to PID 3...
nothing happens after this (endless loop ?). This is my code for `recvmsg()':
[snip code]
Any ideas of what i'm doing wrong ?
There are two errors in your code; both probably contributing to the error (deadlock) that you're seeing.
The first problem is that in your `recvmsg()' code, you have:
MMailBox box = new MMailBox();
Then you proceed to perform operations on this `box' object. However, this `box' is local to this particular `recvmsg()' call. I suspect you have a class variable (field/attribute) called `box' too, since the code you give for `findMsg()' references this. It occurs to me that you might not want the `box' variable in your `recvmsg()' code at all -- your call in there to ``box.findMsg(...)'', is making a call to a static method -- which does not require an object -- you could simply get rid of the reference to `box' and just write ``findMsg(...)'' instead.
The second problem is that when you call `findMsg', you're holding a lock on the local `MMailBox' object you created. Since this `box' is local to `recvmsg()', the effect of `synchronized' is also local -- it doesn't protect anything. However, synchronising on `this.box' won't do much good -- if the code in `findMsg()' calls `MKernel.schedule()', then the process will go to sleep whilst still holding onto the `box' lock. This might prevent other processes from functioning properly.
Should I ever be deleting a sent message from the store if it has been received ?
Yes -- when a message is retrieved by a process (calling `recvmsg()'), it should be removed from the message store.
My question is a follow up to Question 80 (2003). My program does that and the test output is as follows:
MOSS# run UMailRecv process started, PID 3 UMailRecv -- mail-box receiver process UMailRecv: started message sender, pid 4 UMailSend -- mail-box sender process UMailSend: sending sleepy messages to PID 3... UMailSend: done. exiting. UMailRecv: MPosixIf.recvmsg() returned null! -- retry..
Any ideas ?
It looks like your `recvmsg()' call blocks, but doesn't wake up when a message is sent. Rather, it wakes up when the SIGCHLD signal is received (because its child process, `UMailSend', terminated). Check the code in your `sendmsg()' method.
I don't quite understand the `int' result that should be returned by `sendmsg()'. What deems whether or not a `send' has been successful or not ? Is it something to do with whether or not there is a waiting process in the blocked queue ?
Also, what relevance does the result have to the running of the program ?
The majority of the time, the `send' will be successful. If the message is added to the message-queue, then the `send' has been successful (zero is returned). The only failure possibility is if a supplied parameter is `bad', e.g. the `pid' is less than zero, or the `message' is `null'. In such cases, `-MSystem.EINVAL' (invalid value) should be returned. Thus, the return value from `sendmsg()' is not (directly) linked with whether blocked processes were woken up.
As for the relevance to a user-program, if `sendmsg()' returns < 0, then an error occured and the user-program should take appropriate action (perhaps to report the error and terminate).
Sorry if I'm being a bit dense but I've now coded my implementation of `MMailBox' and want to test it. Previous anonymous-questions refer to something called `UMailRecv' & `UMailSend', but where can I find these tests?
The test programs can be downloaded from http://www.cs.kent.ac.uk/~frmb/moss/, in the `download' section. You should download either mailbox-test.zip or mailbox-test.tar.gz, which contain the `UMailRecv.java' and `UMailSend.java' files. See the webpage for compilation information.
Referrers: Question 108 (2003)
I have put the code for a process to be put in the run-queue in the `send' method.
Is this right because I get the idea from the questions it should be in the receive method, or does it not make a difference which is what I am thinking.
You are correct in your first paragraph -- the code that puts a blocked process back on the run-queue should be done in the `send' method. Most of the questions related to blocking are associated with the `receive' part (where the process is placed on an `MWaitQueue' and descheduled).
Hi,
I'm having a problem with message 0 being outputted 3 times and then message 3 once... so I'm missing messages 1 and 2 I think. I've read the new anonymous questions and played around with the code but can't figure it out. This is what I've got :
[snip code]
Can you see anything wrong there?
thank you.
At a guess, the problem is because you're not removing the message from the message-queue before returning it. Instead, you're attempting to remove the `current' process from the `blocked' `MWaitQueue' -- which it won't be on. You should instead be removing the message from the `messages' `ArrayList'.
Referrers: Question 110 (2003)
Is there a special way that MOSS spits out an error message ? Or will a simple ``System.out.println(error)'' or ``System.err.println(error)' do ?
If the error is sufficiently fatal (i.e. the system is in a state where it can't continue), then `MKernel.panic(error)' should be used. Otherwise, either of the two methods you suggest will do. The in-development version of MOSS now has a `MKernel.log_msg(error)' method for this.
Keywords: moss
Ive nearly finished `MMailBox' (1b), however, I am having some trouble with returning error codes.
In `recvmsg() you have to return an `Object', so how can you return an error message such as `EINTR' (interrupted system call) in the case that this process is interupted ? at the moment I am just returning `null', but this will not give an error will it?
Also in `sendmsg()' the only errors I send back are `MSystem.EINVAL' (invalid argument) errors in the case where `to_pid', `from_pid' or `type' are less than 0, or when `msg' is `null'. Should I check for other errors that could occur (like current process list being full) ?
Many thanks.
For `recvmsg()', returning `null' to indicate some form of error is fine. See the answer to Question 52 (2003).
As for `sendmsg()', `EINVAL' is indeed the only error that would normally be returned. There are unlikely to be any other error conditions, but if there were, the `sendmsg()' code should return a suitable error.
Keywords: moss
In (1c) what checks should the `semop()' method in `MPosixIf' method do, before it tries to create/set semaphores ? I guess the first one should check the `op' value to see if it's been given 0 or 1 for create or set.
Yes, that's definitely one thing that you should check for. The other sensible check to make would be for a valid `key' -- keys (when used by user-processes via `MPosixIf') must be not be negative.
public static void findMsg(int destination, int source, int requiredType) { [snip code] }
I am using the above code to find messages in my `ArrayList'. The `System.out.println()' shown at the bottom is something I've added in to help debug.
Why is it showing that `result' is `null' when `result' has, three lines above it, been assigned `currentMsg.msg' ? Surely the variable result should now contain the message that has been found ?
The code here looks fine. I assume `result' is referring to a suitable `private static' variable/attribute. One possibility is that the message was not set correctly in `sendmsg()'. You should probably set `result' to `null' before entering the `while()' loop (unless it's done each time before calling `findMsg()').
Should we be operating on our message pool (for the `MMailBox') within a `synchronized' block in the `sendmsg()' and `recvmsg()' methods ? If not, how can we prevent race hazards ?
Yes, ideally you ought to protect access to the message-pool (and any other shared data) using `synchronized' blocks. This needs to be done reasonably carefully, however.
Referrers: Question 105 (2003)
Maintained by Fred Barnes, last modified Thu May 8 12:58:05 2014 |