Re: System.AccessViolationException
- From: "djc" <noone@xxxxxxxxxxx>
- Date: Thu, 6 Jul 2006 11:47:39 -0400
ok. Here it is. No multiprocessor or dual core. I just copy/pasted the code
from VS 2005 into outlook express. All indentation was lost. I'll leave it
as is assuming the best thing to do if your interested would be to paste
into VS which will hopefully put the indentation back in. If not let me know
and I'll repost and try to make it look good by putting all the indentation
back in etc..
quick overview. I have some real crappy Netgear access points setup in a
warehouse (4 of them) that I routinely have to reboot. To make it easier I
wrote a little CLI that rebooted each one, one at a time (synchronously). I
then decided to make it multithreaded so up to all 4 access points could be
rebooted simultaneously with one quick command. Thats what is pasted below.
It works great in debug but has intermittent issues with a release build,
mostly fails but sometimes seems to work. I get the
system.AccessViolationException at times and other times (noticed more
recently) the output is erroneous. I am using my own class that is basically
a datatable (inherits from system.datatable) with one additional method to
display the data to the console screen nicely (with several overloads). The
powerstate of each access point is monitored by sending pings and the
datatable (consoleTable) is updated to reflect this state so I can see whats
going on - verifying a successfull reboot. I'm describing this since this is
coded for my specific situation and you won't be able to actually run the
program without the same setup.
let me know if I should repost this code and try to put the formatting back
in myself for readability. I will gladly do so. This is kind of driving me
nuts. I am not really supposed to be working on this right now but I'm
anxious to find out whats wrong. I'm assuming I have a logic error somewhere
and that may be hard for anyone else to debug without actually being able to
run this in VS. Again, it compiles fine and does run fine in debug config,
just not in release config????
Main Program follows:
----------------------
using System;
using System.Data;
using System.Threading;
namespace APReset
{
class State
{
internal string theAP;
internal EventWaitHandle eventWaitHandle;
public State(string _theAP, EventWaitHandle _eventWaitHandle)
{
this.theAP = _theAP;
this.eventWaitHandle = _eventWaitHandle;
}
}
class Program
{
//http://TheIPAddress/VxWorks/Reboot?
static DCDev.ConsoleTable ct; //used by all threads for nice output to
console
static volatile int top; //used for top position of the cursor for the
ConsoleTables's display() overload
static int Main(string[] args)
{
if (args.Length < 1 || args.Length > 4)
{
string strHelpMessage = "Usage: apreset n [n] [n] [n] \r\n\r\nReplace 'n'
with 1-4 for specific AP";
strHelpMessage += "\r\n1 = building 43 - front\r\n2 = building 43 -
back\r\n3 = building 45 - front";
strHelpMessage += "\r\n4 = building 45 - back";
Console.WriteLine(strHelpMessage);
//remove following ReadLine(), its for debug only
//Console.ReadLine();
return 1;
}
Console.WriteLine(); //to make a space before main program output - cosmetic
top = Console.CursorTop; // get top cursor position for ConsoleTable's
display() overload
// setup the consoleTable for nice output - access here is safe since there
is only 1 thread at this point
// just lock it- having problems - not sure why
ct = new DCDev.ConsoleTable();
lock (ct)
{
DataColumn col = new DataColumn();
col.ColumnName = "AP";
col.DataType = typeof(string);
col.MaxLength = 5;
ct.Columns.Add(col);
ct.PrimaryKey = new DataColumn[] { ct.Columns["AP"] };
col = new DataColumn();
col.ColumnName = "Status";
col.DataType = typeof(string);
col.MaxLength = 40;
ct.Columns.Add(col);
col = new DataColumn();
col.ColumnName = "PowerState";
col.DataType = typeof(string);
col.MaxLength = 12;
ct.Columns.Add(col);
for (int i = 0; i < args.Length; i++)
{
// create row in ct (console table - which is a datatable) for each AP to
work with
DataRow workRow = ct.NewRow();
workRow["AP"] = args[i].Trim();
workRow["Status"] = "Pending";
workRow["PowerState"] = "Up";
ct.Rows.Add(workRow);
}
ct.AcceptChanges();
}
//to make main thread wait until all others are done before finishing
EventWaitHandle[] eventWaitHandles = new EventWaitHandle[args.Length];
// to pass to worker threads
State state;
try
{
for (int i = 0; i < args.Length; i++)
{
// queue up new thread for each AP so all can run simultaneously
eventWaitHandles[i] = new EventWaitHandle(false,
EventResetMode.ManualReset);
state = new State(args[i].Trim(), eventWaitHandles[i]);
ThreadPool.QueueUserWorkItem(new WaitCallback(workerThreadTask), state);
}
// wait for all worker threads to return
WaitHandle.WaitAll(eventWaitHandles);
Console.WriteLine("All done.");
}
catch (Exception ex)
{
Console.WriteLine("An exception occured: {0}", ex.Message.ToString());
return 1;
}
finally
{
//remove following readLine for build - its for debug only
//Console.ReadLine();
}
return 0;
}
static void workerThreadTask(object state)
{
DCDev.APController myAP = new DCDev.APController();
string usr = "RemovedForPost";
string pwd = "RemovedForPost";
string baseURL = "http://10.10.3.";
string baseIP = "10.10.3.";
State stateInfo = (State)state;
myAP.url = baseURL + stateInfo.theAP + "/VxWorks/Reboot?";
myAP.username = usr;
myAP.password = pwd;
bool firstIteration = true;
bool powerState; //ping result
bool lastPowerState = false; //cache previous result so I only update the
console table if it changed. reduces locks required on ct
//had to set lastPowerState to something here or compiler complained about
using 'unassigned' local var. should not matter what it starts as since it
gets initialized during first iteration of loop
int numOfStateChangesRequired = 2; //default to first ping arriving before
AP actually goes down
UpdateCT(stateInfo.theAP, "Status", "Sending request", "Please wait,
working...");
//if following condition returns true then request was sent and AP responded
OK so we know it was up also
if (myAP.SendRebootRequest())
{
UpdateCT(stateInfo.theAP, "Status", "Request received - rebooting", "Please
wait, working...");
while (numOfStateChangesRequired > 0) //numOfStateChangesRequired defaults
to 2 - assumes first ping is more likely to arrive while AP is still up but
after receiving request to reboot
{
powerState = myAP.IsUp(baseIP + stateInfo.theAP); //returns true if up
(power on)- ping
if (firstIteration)
{
firstIteration = false;
lastPowerState = powerState; //initialize lastPowerState
if (!powerState) //AP went down before first ping arrived; adjust
numOfStateChangesRequired
{
numOfStateChangesRequired = 1;
UpdateCT(stateInfo.theAP, "PowerState", "Down", "Please wait, working...");
//this col defaults to "Up"
}
}
else
{
if (lastPowerState != powerState) //there was a change in power state
{
string colValue;
if (powerState) { colValue = "Up"; } else { colValue = "Down"; }
UpdateCT(stateInfo.theAP, "PowerState", colValue, "Please wait,
working...");
numOfStateChangesRequired--;
}
lastPowerState = powerState;
}
}
//got through all power state changes required so if there was no error,
status is complete
//still need to add check for error - status should change to 'error'
UpdateCT(stateInfo.theAP, "Status", "Complete", "Please wait, working...");
}
else
{
UpdateCT(stateInfo.theAP, "Status", "Error-SendRebootRequest returned
false", "Please wait, working...");
}
stateInfo.eventWaitHandle.Set();
}
static void UpdateCT(string theAP, string colName, string colValue, string
footer)
{
lock (ct)
{
//row should always be found here - shouldn't need to check
DataRow foundRow = ct.Rows.Find(theAP);
foundRow.BeginEdit();
foundRow[colName] = colValue;
foundRow.EndEdit();
ct.AcceptChanges();
ct.Display(0, top, footer); // left, top, - cursor position
}
}
}
}
---------------------------------------------
APController.cs follows:
using System;
using System.Net;
using System.Net.NetworkInformation;
using System.IO;
using System.Text;
namespace DCDev
{
internal class APController
{
private string _url;
private string _usr;
private string _pwd;
public APController(){}
public APController(string url, string usr, string pwd)
{
_url = url;
_usr = usr;
_pwd = pwd;
}
#region PROPERTIES
internal string url
{
get
{
return _url;
}
set
{
_url = value;
}
}
internal string username
{
get
{
return _usr;
}
set
{
_usr = value;
}
}
internal string password
{
get
{
return _pwd;
}
set
{
_pwd = value;
}
}
#endregion
internal bool SendRebootRequest()
{
HttpWebRequest myHTTPRequest = null;
HttpWebResponse myHTTPResponse = null;
StreamReader sr = null;
try
{
myHTTPRequest = (HttpWebRequest)WebRequest.Create(_url);
myHTTPRequest.PreAuthenticate = true;
myHTTPRequest.AllowAutoRedirect = true;
NetworkCredential netCredential = new NetworkCredential();
netCredential.UserName = _usr;
netCredential.Password = _pwd;
myHTTPRequest.Credentials = netCredential;
myHTTPResponse = (HttpWebResponse)myHTTPRequest.GetResponse();
//Console.WriteLine("response status: {0} - from: {1}",
myHTTPResponse.StatusDescription, myHTTPResponse.ResponseUri.Authority);
sr = new StreamReader(myHTTPResponse.GetResponseStream());
string s = sr.ReadToEnd();
//if you ever use this for any APs other than these netgears then the
following 'test' for success needs to change
if (s.IndexOf("Please wait a moment for the AP to reboot...") == -1) return
false;
}
catch (WebException wex)
{
//Console.WriteLine("An exception occured: {0}", wex.Message);
//if (wex.Status == WebExceptionStatus.ProtocolError)
//{
// myHTTPResponse = (HttpWebResponse)wex.Response;
// Console.WriteLine("Protocol Error Code: {0}",
myHTTPResponse.StatusCode.ToString());
//}
return false;
}
finally
{
if (sr != null) sr.Close();
if (myHTTPResponse != null) myHTTPResponse.Close();
}
return true;
}
internal bool IsUp(string ip)
{
// ping - return true if responds, false otherwise
Ping pingSender = new Ping ();
PingOptions options = new PingOptions ();
options.DontFragment = false;
options.Ttl = 128;
// Create buffer of arbitrary data to send in ping packet
string data = "Netgear is gay";
byte[] buffer = Encoding.ASCII.GetBytes (data);
int timeout = 1000; // 1 second
try
{
PingReply reply = pingSender.Send(ip, timeout, buffer, options);
if (reply.Status == IPStatus.Success) { return true; } else { return
false; }
}
catch (Exception ex)
{
//should really do something here to make more robust
return false;
}
}
}
}
-----------------------------------------
ConsoleTable.cs follows:
using System;
using System.Data;
namespace DCDev
{
public class ConsoleTable : DataTable
{
// as it works now this is just a DataTable with my own added method to
display data on console.
// It relies on setting the MaxLenth property of each DataColumn in order to
format the output nicely
public void Display()
{
foreach (DataColumn c in this.Columns)
Console.Write(c.ColumnName.ToString().PadRight(c.MaxLength));
Console.WriteLine();
foreach (DataColumn c in this.Columns)
Console.Write("".PadRight(c.MaxLength, '-'));
Console.WriteLine();
foreach (DataRow r in this.Rows)
{
foreach (DataColumn c in this.Columns)
{
Console.Write(r[c].ToString().PadRight(c.MaxLength));
}
Console.WriteLine();
}
}
public void Display(string footer)
{
foreach (DataColumn c in this.Columns)
Console.Write(c.ColumnName.ToString().PadRight(c.MaxLength));
Console.WriteLine();
foreach (DataColumn c in this.Columns)
Console.Write("".PadRight(c.MaxLength, '-'));
Console.WriteLine();
foreach (DataRow r in this.Rows)
{
foreach (DataColumn c in this.Columns)
{
Console.Write(r[c].ToString().PadRight(c.MaxLength));
}
Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine(footer);
}
public void Display(int x, int y)
{
Console.SetCursorPosition(x, y);
foreach (DataColumn c in this.Columns)
Console.Write(c.ColumnName.ToString().PadRight(c.MaxLength));
Console.WriteLine();
foreach (DataColumn c in this.Columns)
Console.Write("".PadRight(c.MaxLength, '-'));
Console.WriteLine();
foreach (DataRow r in this.Rows)
{
foreach (DataColumn c in this.Columns)
{
Console.Write(r[c].ToString().PadRight(c.MaxLength));
}
Console.WriteLine();
}
}
public void Display(int x, int y, string footer)
{
Console.SetCursorPosition(x, y);
foreach (DataColumn c in this.Columns)
Console.Write(c.ColumnName.ToString().PadRight(c.MaxLength));
Console.WriteLine();
foreach (DataColumn c in this.Columns)
Console.Write("".PadRight(c.MaxLength, '-'));
Console.WriteLine();
foreach (DataRow r in this.Rows)
{
foreach (DataColumn c in this.Columns)
{
Console.Write(r[c].ToString().PadRight(c.MaxLength));
}
Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine(footer);
}
}
}
-------------------------
.
- Follow-Ups:
- Re: System.AccessViolationException
- From: Barry Kelly
- Re: System.AccessViolationException
- References:
- System.AccessViolationException
- From: djc
- Re: System.AccessViolationException
- From: Barry Kelly
- Re: System.AccessViolationException
- From: djc
- Re: System.AccessViolationException
- From: Barry Kelly
- Re: System.AccessViolationException
- From: djc
- Re: System.AccessViolationException
- From: Barry Kelly
- System.AccessViolationException
- Prev by Date: Re: Regular Expression: how to get Filename from Path
- Next by Date: Re: BMP to Metafile
- Previous by thread: Re: System.AccessViolationException
- Next by thread: Re: System.AccessViolationException
- Index(es):
Relevant Pages
|
Loading