B
Bob Grommes
Working with the 1.1 CLR and VS.NET 2003, I have two small console apps that
are executed periodically by a scheduler. One uses ODBC to check a back-end
for certain records and the other uses ODBC to update those same records.
The ODBC driver I'm talking to is capable of locking up the process if the
host is busy or offline, so I launch another thread to access it, then join
it with a 40-second delay.
One app works fine, the other does not. The app that reads works; the one
that writes, the ODBC driver prompts me interactively for a password even
though I'm using the same connection string, with a password. I suspect
this has something to do with thread security but don't know enough about
the inner workings of that to say for sure. Any ideas?
Here is the code that works:
this.odbcConnection.Open();
Thread queryThread = new Thread(new ThreadStart(OdbcExecuteReader));
queryThread.Start();
if (queryThread.Join(TimeSpan.FromSeconds(40)) == false) {
queryThread.Abort();
throw new DataException("Host is busy or hung.");
}
oReader = this.odbcReader; // returned by OdbcExecuteReader()
if (oReader == null) {
throw new DataException("ODBC command failed; see error log for
details.");
}
// Do stuff with the reader
Here's the callback that handles the query:
private void OdbcExecuteReader() {
try {
this.odbcReader =
this.odbcCommand.ExecuteReader(CommandBehavior.SingleResult);
} catch (Exception e) {
this.logger.LogEvent(String.Format("Error executing ODBC
command:{0}{1}{0}{0}Connection string: {2}{0}{0}{3}",
Environment.NewLine,
this.odbcCommand.CommandText,
this.odbcCommand.Connection.ConnectionString,
e.ToString()),
EventLogEntryType.Error);
}
}
Well and good.
Now here's the problem code:
this.odbcConnection.Open();
Thread updateThread = new Thread(new ThreadStart(OdbcExecuteNonQuery));
updateThread.Start();
if (updateThread.Join(TimeSpan.FromSeconds(40)) == false) {
updateThread.Abort();
throw new DataException("Host is busy or hung.");
} else if (this.odbcThreadSucceeded == false) {
throw new DataException("ODBC command failed; see error log for
details.");
}
.... and the callback:
private void OdbcExecuteNonQuery() {
this.odbcThreadSucceeded = false;
try {
this.odbcCommand.ExecuteNonQuery();
this.odbcThreadSucceeded = true;
} catch (Exception e) {
this.logger.LogEvent(String.Format("Error executing ODBC
command:{0}{1}{0}{0}Connection string: {2}{0}{0}{3}",
Environment.NewLine,
this.odbcCommand.CommandText,
this.odbcCommand.Connection.ConnectionString,
e.ToString()),
EventLogEntryType.Error);
}
}
The update doesn't acutally happen when I provide the correct password;
although no exceptions are thrown; but that may be a separate problem
(incorrect WHERE clause). I'm looking into that.
The ODBC driver is for FileMaker. For the unitiated, you can think of
FileMaker as a flat-file manager. The password sent in the connection
string is the password for opening the file. It works for reading, but not
for writing. Yet the password controls total access, not just reading.
There isn't even a capability in the product to provide different passwords
for different access levels; it's all-or-nothing.
Any pointers about why a connection opened in one thread would not pass
security muster from another thread would be appreciated.
--Bob
are executed periodically by a scheduler. One uses ODBC to check a back-end
for certain records and the other uses ODBC to update those same records.
The ODBC driver I'm talking to is capable of locking up the process if the
host is busy or offline, so I launch another thread to access it, then join
it with a 40-second delay.
One app works fine, the other does not. The app that reads works; the one
that writes, the ODBC driver prompts me interactively for a password even
though I'm using the same connection string, with a password. I suspect
this has something to do with thread security but don't know enough about
the inner workings of that to say for sure. Any ideas?
Here is the code that works:
this.odbcConnection.Open();
Thread queryThread = new Thread(new ThreadStart(OdbcExecuteReader));
queryThread.Start();
if (queryThread.Join(TimeSpan.FromSeconds(40)) == false) {
queryThread.Abort();
throw new DataException("Host is busy or hung.");
}
oReader = this.odbcReader; // returned by OdbcExecuteReader()
if (oReader == null) {
throw new DataException("ODBC command failed; see error log for
details.");
}
// Do stuff with the reader
Here's the callback that handles the query:
private void OdbcExecuteReader() {
try {
this.odbcReader =
this.odbcCommand.ExecuteReader(CommandBehavior.SingleResult);
} catch (Exception e) {
this.logger.LogEvent(String.Format("Error executing ODBC
command:{0}{1}{0}{0}Connection string: {2}{0}{0}{3}",
Environment.NewLine,
this.odbcCommand.CommandText,
this.odbcCommand.Connection.ConnectionString,
e.ToString()),
EventLogEntryType.Error);
}
}
Well and good.
Now here's the problem code:
this.odbcConnection.Open();
Thread updateThread = new Thread(new ThreadStart(OdbcExecuteNonQuery));
updateThread.Start();
if (updateThread.Join(TimeSpan.FromSeconds(40)) == false) {
updateThread.Abort();
throw new DataException("Host is busy or hung.");
} else if (this.odbcThreadSucceeded == false) {
throw new DataException("ODBC command failed; see error log for
details.");
}
.... and the callback:
private void OdbcExecuteNonQuery() {
this.odbcThreadSucceeded = false;
try {
this.odbcCommand.ExecuteNonQuery();
this.odbcThreadSucceeded = true;
} catch (Exception e) {
this.logger.LogEvent(String.Format("Error executing ODBC
command:{0}{1}{0}{0}Connection string: {2}{0}{0}{3}",
Environment.NewLine,
this.odbcCommand.CommandText,
this.odbcCommand.Connection.ConnectionString,
e.ToString()),
EventLogEntryType.Error);
}
}
The update doesn't acutally happen when I provide the correct password;
although no exceptions are thrown; but that may be a separate problem
(incorrect WHERE clause). I'm looking into that.
The ODBC driver is for FileMaker. For the unitiated, you can think of
FileMaker as a flat-file manager. The password sent in the connection
string is the password for opening the file. It works for reading, but not
for writing. Yet the password controls total access, not just reading.
There isn't even a capability in the product to provide different passwords
for different access levels; it's all-or-nothing.
Any pointers about why a connection opened in one thread would not pass
security muster from another thread would be appreciated.
--Bob